23

私はscrapyウェブサイトからスクレイプデータを選別するために使用しています。ただし、必要なデータは html 自体ではなく、javascript からのものです。だから、私の質問は:

そのような場合の値 (テキスト値) を取得するにはどうすればよいですか?

これは、私がスクレイプをスクリーニングしようとしているサイトです: https://www.mcdonalds.com.sg/locate-us/

取得しようとしている属性: 住所、連絡先、営業時間。

Chrome ブラウザー内で「右クリック」、「ソースの表示」を行うと、そのような値が HTML で使用できないことがわかります。


編集

ポールさん、おっしゃる通りに実行しadmin-ajax.php、死体を見つけて見ましたが、今は本当に困っています。

json オブジェクトから値を取得し、それを自分の変数フィールドに格納するにはどうすればよいですか? 属性を 1 つだけ実行する方法を、一般の人や、スクレイピーを始めたばかりの人にも共有できれば幸いです。

これまでの私のコードは次のとおりです

アイテム.py

class McDonaldsItem(Item):
name = Field()
address = Field()
postal = Field()
hours = Field()

McDonalds.py

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
import re

from fastfood.items import McDonaldsItem

class McDonaldSpider(BaseSpider):
name = "mcdonalds"
allowed_domains = ["mcdonalds.com.sg"]
start_urls = ["https://www.mcdonalds.com.sg/locate-us/"]

def parse_json(self, response):

    js = json.loads(response.body)
    pprint.pprint(js)

長い編集は申し訳ありませんが、要するに、json値を属性に保存するにはどうすればよいですか? 例えば

***item['address'] = * 取得方法 ****

PS、これが役立つかどうかはわかりませんが、コマンドラインでこれらのスクリプトを実行します

スクラップクロール mcdonalds -o McDonalds.json -t json (すべてのデータを json ファイルに保存するため)

私がどれほど感謝しているかを強調することはできません。これをあなたに尋ねるのはちょっと不合理だと思いますが、時間がなくても大丈夫です。

4

2 に答える 2

21

(これをscrapy-usersメーリング リストに投稿しましたが、Paul の提案により、shellコマンド インタラクションで回答を補完するため、ここに投稿します。)

一般に、サードパーティのサービスを使用してデータの視覚化 (マップ、テーブルなど) をレンダリングする Web サイトは、何らかの方法でデータを送信する必要があり、ほとんどの場合、このデータはブラウザーからアクセスできます。

この場合、インスペクション (つまり、ブラウザによって行われたリクエストの調査) は、データが POST リクエストからhttps://www.mcdonalds.com.sg/wp-admin/admin-ajax.phpにロードされていることを示しています。

したがって、基本的には、必要なすべてのデータが適切な json 形式であり、すぐに使用できます。

Scrapy はshell、スパイダーを作成する前に Web サイトを考えるのに非常に便利なコマンドを提供します。

$ scrapy shell https://www.mcdonalds.com.sg/locate-us/
2013-09-27 00:44:14-0400 [scrapy] INFO: Scrapy 0.16.5 started (bot: scrapybot)
...

In [1]: from scrapy.http import FormRequest

In [2]: url = 'https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php'

In [3]: payload = {'action': 'ws_search_store_location', 'store_name':'0', 'store_area':'0', 'store_type':'0'}

In [4]: req = FormRequest(url, formdata=payload)

In [5]: fetch(req)
2013-09-27 00:45:13-0400 [default] DEBUG: Crawled (200) <POST https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php> (referer: None)
...

In [6]: import json

In [7]: data = json.loads(response.body)

In [8]: len(data['stores']['listing'])
Out[8]: 127

In [9]: data['stores']['listing'][0]
Out[9]: 
{u'address': u'678A Woodlands Avenue 6<br/>#01-05<br/>Singapore 731678',
 u'city': u'Singapore',
 u'id': 78,
 u'lat': u'1.440409',
 u'lon': u'103.801489',
 u'name': u"McDonald's Admiralty",
 u'op_hours': u'24 hours<br>\r\nDessert Kiosk: 0900-0100',
 u'phone': u'68940513',
 u'region': u'north',
 u'type': [u'24hrs', u'dessert_kiosk'],
 u'zip': u'731678'}

つまり、スパイダーで上記を返す必要がありFormRequest(...)、コールバックでjsonオブジェクトをロードしresponse.body、最後にリスト内の各ストアのデータに対してdata['stores']['listing']、必要な値を持つアイテムを作成します。

このようなもの:

class McDonaldSpider(BaseSpider):
    name = "mcdonalds"
    allowed_domains = ["mcdonalds.com.sg"]
    start_urls = ["https://www.mcdonalds.com.sg/locate-us/"]

    def parse(self, response):
        # This receives the response from the start url. But we don't do anything with it.
        url = 'https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php'
        payload = {'action': 'ws_search_store_location', 'store_name':'0', 'store_area':'0', 'store_type':'0'}
        return FormRequest(url, formdata=payload, callback=self.parse_stores)

    def parse_stores(self, response):
        data = json.loads(response.body)
        for store in data['stores']['listing']:
            yield McDonaldsItem(name=store['name'], address=store['address'])
于 2013-09-27T12:51:59.190 に答える