web-dev-qa-db-ja.com

Pythonまたはjsから追加されたコンテンツ)のスクリプトタグ内の変数のデータを取得する

rllib and Beautiful Soupを使用している別のURLからデータをフェッチしたいのですが、データはテーブルタグ内にあります(Firefoxコンソールを使用して把握しています)。しかし、彼のIDを使用してテーブルをフェッチしようとすると、結果はNoneになります。このテーブルは、いくつかのjsコードを介して動的に追加する必要があると思います。

私は両方のパーサーをすべて試しました'lxml'、 'html5lib'ですが、それでもそのテーブルデータを取得できません。

私はもう一つも試しました:

web = urllib.urlopen("my url")
html = web.read()
soup = BeautifulSoup(html, 'lxml')
js  = soup.find("script")
ss = js.prettify()
print ss

結果:

<script type="text/javascript">
 myPage = 'ETFs';
        sectionId = 'liQuotes'; //section tab
        breadCrumbId = 'qQuotes'; //page
        is_dartSite = "quotes";
        is_dartZone = "news";
        propVar = "ETFs";
</script>

しかし、今はこれらのjs変数のデータを取得する方法がわかりません。

今、私は2つのオプションがあります。テーブルのコンテンツを取得するか、js変数を取得します。それらのいずれかが私のタスクを実行できますが、残念ながらこれらを取得する方法がわからないので、問題のいずれかを解決する方法を教えてください。

ありがとう

12
Inforian

[〜#〜]編集[〜#〜]

これは re モジュールを使用してデータを抽出し、それをJSONとしてロードするトリックを実行します。

import urllib
import json
import re
from bs4 import BeautifulSoup

web = urllib.urlopen("http://www.nasdaq.com/quotes/nasdaq-financial-100-stocks.aspx")
soup = BeautifulSoup(web.read(), 'lxml')
data  = soup.find_all("script")[19].string
p = re.compile('var table_body = (.*?);')
m = p.match(data)
stocks = json.loads(m.groups()[0])

>>> for stock in stocks:
...     print stock
... 
[u'ASPS', u'Altisource Portfolio Solutions S.A.', 116.96, 2.2, 1.92, 86635, u'N', u'N']
[u'AGNC', u'American Capital Agency Corp.', 23.76, 0.13, 0.55, 3184303, u'N', u'N']
.
.
.
[u'ZION', u'Zions Bancorporation', 29.79, 0.46, 1.57, 2154017, u'N', u'N']

これに関する問題は、スクリプトタグのオフセットがハードコードされており、ページ内でそれを特定する信頼できる方法がないことです。ページを変更すると、コードが破損する可能性があります。

元の回答

データをスクリーンスクレイピングしようとするのではなく、同じデータのCSV表現を http://www.nasdaq.com/quotes/nasdaq-100-stocks.aspx?render=download からダウンロードできます。 。

次に、Python csv モジュールを使用して、それを解析および処理します。これはより便利であるだけでなく、HTMLに変更を加えると簡単に回復できるため、より回復力のあるソリューションになります。画面スクレイピングコードを壊します。

それ以外の場合、実際のHTMLを見ると、ページ内の次のスクリプトタグでデータを利用できることがわかります。

<script type="text/javascript">var table_body = [["ATVI", "Activision Blizzard, Inc", 20.92, 0.21, 1.01, 6182877,  .1, "N", "N"],
["ADBE", "Adobe Systems Incorporated", 66.91, 1.44, 2.2, 3629837,  .6, "N", "N"],
["AKAM", "Akamai Technologies, Inc.", 57.47, 1.57, 2.81, 2697834,  .3, "N", "N"],
["ALXN", "Alexion Pharmaceuticals, Inc.", 170.2, 0.7, 0.41, 659817,  .1, "N", "N"],
["ALTR", "Altera Corporation", 33.82, -0.06, -0.18, 1928706,  .0, "N", "N"],
["AMZN", "Amazon.com, Inc.", 329.67, 6.1, 1.89, 5246300,  2.5, "N", "N"],
....
["YHOO", "Yahoo! Inc.", 35.92, 0.98, 2.8, 18705720,  .9, "N", "N"]];
11
mhawke

@mhawkeの回答に追加するだけで、スクリプトタグのオフセットをハードコーディングするのではなく、すべてのスクリプトタグをループして、パターンに一致するものに一致させます。

web = urllib.urlopen("http://www.nasdaq.com/quotes/nasdaq-financial-100-stocks.aspx")
pattern = re.compile('var table_body = (.*?);')

soup = BeautifulSoup(web.read(), "lxml")
scripts = soup.find_all('script')
for script in scripts:
   if(pattern.match(str(script.string))):
       data = pattern.match(script.string)
       stock = json.loads(data.groups()[0])
       print stock
2
parkerproject