リクエストを使用してWebページからの正確な結果を解析できません


8

私はウェブページから2つのフィールドを解析するためにpythonでスクリプトを作成しました- total revenueそしてそれは心配dateです。私が求めているフィールドはJavaScriptで暗号化されています。それらは、json配列内のページソースで使用できます。次のスクリプトは、これらの2つのフィールドを適宜解析できます。

ただし、問題は、そのページに表示される日付がページソースで使用可能な日付と異なることです。

ウェブページのリンク

そのWebページの日付は次のようである。この

ページのソースの日付は次のようである。この

明らかに1日の変動があります。

このタブをクリックすると、そのWebページにアクセスした後Quarterly、そこに結果が表示されます。

私は試しました:

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)

私が得た結果(100万の収益):

802000000 2019-06-30

私が得たい結果:

802000000 2019-06-29

このティッカーを試してみるとAAPL、正確な日付が取得されるため、サブトレースまたは日を追加することはできません。

そのサイトから正確な日付を取得するにはどうすればよいですか?

ところで、私はセレンを使用してそれらを取得する方法を知っているので、に固執したいと思いrequestsます。


3
日付が最大で1日ずれている場合、私の最初の推測は、その違いはタイムゾーン変換によるものだと思います。
Janne Karila、

1
結果を確認するために別の場所を使用してvpnをアクティブにしてみましたが、バリエーションはまだそこにあります@Janne Karila。
MITHU

私はあなたのコードを試したところ、printステートメントの出力はページ(2019-6-30)と同じでした。
Jack Fleeting

はい、あなたは@Jack Fleetingですが、他のティッカーは確かに異なります。実際には、別の結果になるかもしれません。この時点で、Janne Karilaは彼の最初の推測では正しかったようです。私はそれを修正する方法があるかもしれないと思います。
MITHU

正しい日付と間違った日付の銘柄記号をいくつか提供してもらえますか?
人生は複雑です

回答:


2

コメントで述べたように、日付を適切なタイムゾーン(EST)に変換する必要がありdateutilます。これは、datetimeおよびで実行できます。

これが実際の例です:

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)

それは私が期待していた結果のようです。のよう06-29-2019に日付をフォーマットできません2019-06-29 19:00:00-05:00か?ありがとう。
ミトゥ

1
@MITHU更新でこれを追加しました。最初に、を使用してdatetimeオブジェクトを日付に変換する.date()必要があり、次にを使用.strftimeして目的の形式に変換する必要があります。
モニカを

2
NVDAこのリンクにつながるこのティッカーを試してみると、違いがさらに大きいことがわかります。
ミトゥ

@MITHUストレンジ。これはNVIDIA、ESTにも含まれているため、TZは問題ではない可能性が高いことを意味します。私は解決策を検討しますが、なぜこれが起こっているのかについて私は無知です。
モニカを

2

この回答の更新されたセクションは、日付の違いの根本的な原因を概説しています。


元の答え


JSONの生の値の一部はUNIXタイムスタンプです。

変更を加えたコードからの参照:

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'、 'raw':1564272000}

1564272000は1970年1月1日からの経過秒数です。この日付はUnixエポックの始まりであり、時刻は協定世界時(UTC)です。 1564272000は、07 12:00 am(UTC)に相当します。

組み込みのPython関数を使用して、これらのタイムスタンプを標準の日時形式に変換できます。

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

これでも、JSONの日付と列の日付が異なる場合があるという元の問題は解決されません。しかし、ここに、発生している日付の不一致に関する私の現在の仮説があります。

  1. JSON形式から抽出されている日付(FMTと生)root.App.mainは、協定世界時(UTC)です。rawのUNIXタイムスタンプのため、これは明らかです。

  2. テーブルの列に表示されている日付は、東部標準時(EST)タイムゾーンのようです。ESTは現在UTC-4です。つまり、2019-07-28 22:00(10pm)ESTは2019-07-29 02:00(2am)UTCになります。tracerouteの 結果に基づいて、finance.yahoo.comをホストするサーバーは米国にあるようです。これらの値はjsonファイルにもあります。

    • 「exchangeTimezoneName」:「America / New_York」
    • 'exchangeTimezoneShortName': 'EDT'
  3. また、日付の違いの一部が、サイトが使用する基礎となるReactコードにリンクされている可能性もあります。コードが表示されないため、この問題の診断は困難です。

現時点では、最良の解決策は、UNIXタイムスタンプをグラウンドトゥルースタイムリファレンスとして使用することだと思います。この参照は、テーブルの列の日付を置き換えるために使用できます。

確かに、JSONファイルと列の間で何らかのタイプの変換が行われています。

NVIDIA JSONファイル: 'endDate':{'raw':1561766400、 'fmt': '2019-06-29'}

NVIDIA関連の総収益の列:2019年6月30日

ただし、合計収益列の日付は6/28/2019(EDT)である必要があります。これは、1561766400の UNIXタイムスタンプが06/29/2019 12:00 am(UTC)であるためです。

DELLとの違いは、基本的なUNIXタイムスタンプおよびEDTタイムスタンプ変換よりも大きいです。

DELL JSONファイル:{"raw":1564704000、 "fmt": "2019-08-02"}

DELLに関連する総収益の列:2019年7月31日

UNIXタイムスタンプをEDTタイムスタンプに変換すると、結果は2019年8月1日になりますが、DELLの例ではそうではなく、2019年7月31日です。Yahooコードベース内の何かがこの違いを引き起こしているに違いありません。

Reactがこれらの日付の違いの原因である可能性があると私は信じ始めていますが、さらに調査を行わなければ、確信が持てません。

Reactが根本的な原因である場合、最良のオプションは、JSONデータからの日付要素を使用することです。


回答の更新2019年10月17日


この問題は非常に興味深いものです。これらの列の日付は、日付の会話の問題ではなく、会社の正式な四半期末に関連しているようです。

ここにいくつかの例があります

  • Apple Inc.(AAPL)
  • Atlassian Corporation Plc(TEAM)
  • Arrowhead Pharmaceuticals、Inc.(ARWR):

列の日付は次のとおりです。

  • 2019年6月30日
  • 2019年3月31日
  • 2018年12月31日
  • 2018年9月30日

これらの日付はこれらの会計四半期に一致します。

  • 第1四半期(Q1):1月1日〜3月31日。
  • 第2四半期(Q2):4月1日〜6月30日。
  • 第3四半期(Q3):7月1日〜9月30日。
  • 第4四半期(Q4):10月1日〜12月31日

このDELLの例が示すように、これらの会計四半期の終了日は大きく異なる可能性があります。

DELL(NASDAQに掲載)会計四半期末:2019年7月

Yahoo Finance 列の日付:2019年7月31日

JSONの日付:2019-08-02

会社のウェブサイトから:

Dell Technologiesの会計年度はいつ終了しますか?

  • 私たちの会計年度は、1月31日から最も近い金曜日に終了する52週間または53週間です。2020会計年度は2020年1月31日に終了します。それ以前の会計年度については、以下のリストを参照してください。2019会計年度は2月1日に終了2019 2018年2月2日に終了した2018年度2017年2月3日に終了した2017年度2016年1月29日に終了した2016年度2015年1月30日に終了した2015年度2015年1月30日に終了した2014年度2014 2013年2月1日に終了した2013年度

デルの会計四半期

注: 05-03-19および08-02-19の日付。

これらは、DELLのJSON四半期データからのものです。

  • {「生」:1564704000、「fmt」:「2019-08-02」}
  • {「生」:1556841600、「fmt」:「2019-05-03」}

これらの列の日付は、会社の会計四半期の終了日にリンクされているようです。そのため、JSONの日付を主要な参照要素として使用するか、対応する列の日付を使用することをお勧めします。

PS Yahooで発生している日付のブードゥーには、休日、週末、月末に基づいてこれらの列の四半期の日付を移動するように見えるため、ある種の日付ブードゥーがあります。


1

代わりに取得するfmtのをconcerning_date、それはタイムスタンプを取得する方が良いでしょう。

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

上記の例では、結果が得られます 1561852800では、特定のタイムゾーンの日付に転送できるます。(ヒント:使用datetimeとしますpytz)。このタイムスタンプは、タイムゾーンに基づいて次の結果をもたらします。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.