Không thể phân tích kết quả chính xác từ một trang web bằng các yêu cầu


8

Tôi đã tạo một tập lệnh bằng python để phân tích hai trường từ một trang web - total revenuevà nó liên quan date. Các lĩnh vực tôi theo sau được mã hóa javascript. Chúng có sẵn trong nguồn trang trong mảng json. Kịch bản sau đây có thể phân tích hai trường đó cho phù hợp.

Tuy nhiên, vấn đề là ngày hiển thị trong trang đó khác với ngày có sẵn trong nguồn trang.

Liên kết trang web

Ngày trong trang web đó là như thế này

Ngày trong nguồn trang là như thế này

Rõ ràng có một biến thể của một ngày.

Sau khi truy cập trang web đó khi bạn nhấp vào tab này, Quarterlybạn có thể thấy kết quả ở đó:

Tôi đã thử với:

import re
import json
import requests

url = 'https://finance.yahoo.com/quote/GTX/financials?p=GTX'

res = requests.get(url)
data = re.findall(r'root.App.main[^{]+(.*);',res.text)[0]
jsoncontent = json.loads(data)
container = jsoncontent['context']['dispatcher']['stores']['QuoteSummaryStore']['incomeStatementHistoryQuarterly']['incomeStatementHistory']
total_revenue = container[0]['totalRevenue']['raw']
concerning_date = container[0]['endDate']['fmt']
print(total_revenue,concerning_date)

Kết quả tôi nhận được (doanh thu tính bằng triệu):

802000000 2019-06-30

Kết quả tôi muốn nhận được:

802000000 2019-06-29

Khi tôi thử với mã này AAPL, tôi nhận được ngày chính xác, vì vậy, trừ hoặc thêm một ngày không phải là một lựa chọn.

Làm thế nào tôi có thể có được ngày chính xác từ trang web đó ?

Btw, tôi biết làm thế nào để có được chúng bằng cách sử dụng selen, vì vậy tôi chỉ muốn bám vào requests.


3
Nếu ngày hết hạn trong một ngày, dự đoán đầu tiên của tôi sẽ là sự khác biệt đến từ chuyển đổi múi giờ.
Janne Karila

1
Tôi đã thử kích hoạt vpn bằng cách sử dụng vị trí khác nhau để xem kết quả nhưng biến thể vẫn còn đó @Janne Karila.
MITHU

Tôi vừa thử mã của bạn và đầu ra câu lệnh in giống như trên trang (2019-6-30).
Jack Fleeting

Vâng, đúng bạn là @Jack Fleeting nhưng các mã khác chắc chắn sẽ thay đổi. Trong thực tế, bạn có thể nhận được kết quả khác nhau một thời gian khác. Tại thời điểm này, dường như Janne Karila đã đúng trong lần đoán đầu tiên của mình. Tôi cho rằng có thể có bất kỳ cách nào để khắc phục điều đó.
MITHU

Bạn có thể vui lòng cung cấp thêm một số biểu tượng chứng khoán với ngày chính xác và những biểu tượng có ngày sai?
Cuộc sống phức tạp

Câu trả lời:


2

Như đã đề cập trong các bình luận, bạn cần chuyển đổi ngày thành múi giờ thích hợp (EST), có thể được thực hiện với datetime và dateutil.

Dưới đây là một ví dụ hoạt động:

import re
import json
import requests
from datetime import datetime, timezone
from dateutil import tz

url = 'https://finance.yahoo.com/quote/GTX/financials?p=GTX'

res = requests.get(url)
data = re.findall(r'root.App.main[^{]+(.*);',res.text)[0]
jsoncontent = json.loads(data)
container = jsoncontent['context']['dispatcher']['stores']['QuoteSummaryStore']['incomeStatementHistoryQuarterly']['incomeStatementHistory']
total_revenue = container[0]['totalRevenue']['raw']

EST = tz.gettz('EST')
raw_date = datetime.fromtimestamp(container[0]['endDate']['raw'], tz=EST)
concerning_date = raw_date.date().strftime('%d-%m-%Y')
print(total_revenue, concerning_date)

Nó dường như là kết quả mà tôi mong đợi có được. Tôi có thể không định dạng ngày như 06-29-2019thay vì 2019-06-29 19:00:00-05:00? Cảm ơn.
MITHU

1
@MITHU Tôi đã thêm điều này trong một bản cập nhật. Trước tiên, bạn cần chuyển đổi đối tượng datetime thành một ngày bằng cách sử dụng .date(), sau đó bạn cần sử dụng .strftimeđể chuyển đổi nó thành định dạng mong muốn.
Phục hồi lại

2
Nếu tôi thử với mã NVDAnày sẽ dẫn đến liên kết này , tôi thấy rằng sự khác biệt thậm chí còn lớn hơn.
MITHU

@MITHU Lạ. Điều đó có nghĩa là TZ có thể không phải là vấn đề, vì NVIDIAcũng ở EST. Tôi sẽ xem xét một giải pháp, nhưng bây giờ tôi không biết tại sao điều này lại xảy ra.
Phục hồi Monica

2

Phần cập nhật của câu trả lời này nêu ra nguyên nhân gốc rễ của sự khác biệt ngày.


CÂU TRẢ LỜI


Một số giá trị thô trong JSON của bạn là dấu thời gian UNIX.

Tham chiếu từ mã của bạn với các sửa đổi:

concerning_date_fmt = container[0]['endDate']['fmt']
concerning_date_raw = container[0]['endDate']['raw']
print(f'{concerning_date} -- {concerning_date_raw}')
# output 
2019-07-28 -- 1564272000 

'endDate': {'fmt': '2019-07-28', 'thô': 1564272000}

1564272000 là số giây trôi qua kể từ ngày 1 tháng 1 năm 1970. Ngày này là ngày bắt đầu của Thời đại Unix và thời gian là trong Giờ quốc tế phối hợp (UTC). 1564272000 tương đương với: 28/07/2019 12:00 sáng (UTC).

Bạn có thể chuyển đổi các dấu thời gian này sang định dạng datetime tiêu chuẩn bằng cách sử dụng các hàm Python tích hợp

from datetime import datetime
unix_timestamp = int('1548547200')

converted_timestamp = datetime.utcfromtimestamp(unix_timestamp).strftime('%Y-%m-%dT%H:%M:%SZ')
print (converted_timestamp)
# output Coordinated Universal Time (or UTC)
2019-07-28T00:00:00Z

reformatted_timestamp = datetime.strptime(converted_timestamp, '%Y-%m-%dT%H:%M:%SZ').strftime('%d-%m-%Y')
print (reformatted_timestamp)
# output
28-07-2019

Điều này vẫn không giải quyết được vấn đề ban đầu của bạn liên quan đến ngày JSON và ngày cột khác nhau. Nhưng đây là giả thuyết hiện tại của tôi liên quan đến sự chênh lệch ngày đang xảy ra.

  1. Ngày json (fmt và raw) đang được trích xuất từ root.App.main đang trong Giờ phối hợp quốc tế (UTC). Điều này là rõ ràng vì dấu thời gian UNIX ở dạng thô .

  2. Các ngày được hiển thị trong các cột của bảng dường như nằm trong múi giờ Giờ chuẩn miền đông (EST). EST hiện là UTC-4. Điều đó có nghĩa là 2019-07-28 22:00 (10pm) EST sẽ là 2019-07-29 02:00 (2am) UTC. Máy chủ lưu trữ tài chính.yahoo.com dường như ở Hoa Kỳ, dựa trên kết quả theo dõi . Các giá trị này cũng nằm trong tệp json :

    • 'exchangeTimezoneName': 'America / New_York'
    • 'exchangeTimezoneShortName': 'EDT'
  3. Cũng có khả năng một số khác biệt về ngày tháng được liên kết với mã React cơ bản mà trang web sử dụng. Vấn đề này khó chẩn đoán hơn, vì mã không hiển thị.

Tại thời điểm này tôi tin rằng giải pháp tốt nhất sẽ là sử dụng dấu thời gian UNIX làm tài liệu tham khảo thời gian thực của bạn. Tham chiếu này có thể được sử dụng để thay thế ngày của cột bảng.

Chắc chắn có một số loại chuyển đổi xảy ra giữa tệp JSON và các cột.

NVIDIA JSON FILE: 'endDate': {'raw': 1561766400, 'fmt': '2019-06-29'}

Cột Tổng doanh thu liên kết của NVIDIA: 30/12/2019

NHƯNG ngày cột Tổng doanh thu phải là 6/11/2019 (EDT), vì dấu thời gian UNIX cho 1561766400 là 12:00 sáng (UTC).

Sự chênh lệch với DELL lớn hơn dấu thời gian UNIX cơ bản và chuyển đổi dấu thời gian EDT.

DELL JSON FILE: {"raw": 1564704000, "fmt": "2019-08-02"}

Cột tổng doanh thu của DELL: 31/07/2019

Nếu chúng ta chuyển đổi dấu thời gian UNIX thành dấu thời gian EDT, kết quả sẽ là 8/1/2019, nhưng đó không phải là trường hợp trong ví dụ DELL, đó là ngày 31 tháng 7 năm 2019. Một cái gì đó trong cơ sở mã Yahoo phải gây ra sự khác biệt này.

Tôi bắt đầu tin rằng React có thể là thủ phạm với những khác biệt về ngày tháng này, nhưng tôi không thể chắc chắn nếu không nghiên cứu thêm.

Nếu React là nguyên nhân gốc thì tùy chọn tốt nhất sẽ là sử dụng các phần tử ngày từ dữ liệu JSON.


CẬP NHẬT TRẢ LỜI 10-17-2019


Vấn đề này rất thú vị, vì dường như những ngày cột này được liên kết với kết thúc chính thức của quý tài chính của công ty và không phải là vấn đề cuộc trò chuyện ngày.

Dưới đây là một số ví dụ cho

  • Apple Inc. (AAPL)
  • Tập đoàn Atlassian Plc (TEAM)
  • Arrowhead Enterprises, Inc. (ARWR):

Ngày cột của họ là:

  • 30 tháng 6 năm 2019
  • 31/03/2019
  • 31/12/2018
  • 30/9/2018

Những ngày này phù hợp với các quý tài chính.

  • Quý 1 (Q1): 1 tháng 1 - 31 tháng 3.
  • Quý 2 (quý 2): 1 tháng 4 - 30 tháng 6.
  • Quý 3 (Quý 3): 1 tháng 7 - 30 tháng 9.
  • Quý 4 (Q4): 1 tháng 10 - 31 tháng 12

Những ngày kết thúc quý tài chính này có thể thay đổi lớn như ví dụ DELL này cho thấy.

DELL (đăng trong NASDAQ) Cuối quý tài chính: tháng 7 năm 2019

Tài chính yahoo Cột ngày: 31/07/2019

Ngày JSON: 2019-08 / 02

Từ trang web của công ty:

Khi nào năm tài chính của Dell Technologies kết thúc?

  • Năm tài chính của chúng tôi là giai đoạn 52 hoặc 53 tuần kết thúc vào thứ Sáu gần nhất vào ngày 31 tháng 1. Năm tài chính 2020 của chúng tôi sẽ kết thúc vào ngày 31 tháng 1 năm 2020. Đối với các năm tài chính trước, hãy xem danh sách dưới đây: Năm tài chính 2019 của chúng tôi kết thúc vào ngày 1 tháng 2, 2019 Năm tài chính 2018 của chúng tôi kết thúc vào ngày 2 tháng 2 năm 2018 Năm tài chính 2017 của chúng tôi kết thúc vào ngày 3 tháng 2 năm 2017 Năm tài chính 2016 của chúng tôi kết thúc vào ngày 29 tháng 1 năm 2016 Năm tài chính 2015 của chúng tôi kết thúc vào ngày 30 tháng 1 năm 2015 Năm tài chính 2014 của chúng tôi kết thúc vào ngày 31 tháng 1 năm 2015 2014 Năm tài chính 2013 của chúng tôi kết thúc vào ngày 1 tháng 2 năm 2013

khu tài chính của dell

LƯU Ý: Ngày 05-03-19 và 08-02-19.

Đây là từ dữ liệu quý JSON cho DELL:

  • {'thô': 1564704000, 'fmt': '2019-08-02'}
  • {'thô': 1556841600, 'fmt': '2019-05-03'}

Có vẻ như các ngày cột này được liên kết với ngày kết thúc quý tài chính của công ty. Vì vậy, tôi khuyên bạn nên sử dụng ngày JSON làm phần tử tham chiếu chính hoặc ngày cột tương ứng.

PS Có một số loại voodoo ngày xảy ra tại Yahoo, bởi vì họ dường như di chuyển các ngày quý này dựa trên các ngày lễ, cuối tuần và cuối tháng.


1

Thay vì nhận được fmtcủa concerning_date, Đó là tốt hơn để có được những dấu thời gian.

concerning_date = container[0]['endDate']['raw']

Trong ví dụ trên, bạn sẽ nhận được kết quả 1561852800mà bạn có thể chuyển vào một ngày với múi giờ nhất định. (Gợi ý: sử dụng datetimepytz). Dấu thời gian này sẽ mang lại kết quả sau dựa trên múi giờ:

Date in Los Angeles*: 29/06/2019, 17:00:00
Date in Berlin* :30/06/2019, 02:00:00
Date in Beijing*: 30/06/2019, 07:00:00
Date in New York* :29/06/2019, 19:00:00
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.