2013-09-26 62 views
20

我正在使用scrapy來從網站上刮取數據。但是,我想要的數據不在html本身內部,而是來自javascript。所以,我的問題是:Scrapy,在Javascript中刪除數據

如何獲取這些情況下的值(文本值)?

這是我想屏幕刮網站: https://www.mcdonalds.com.sg/locate-us/

屬性我試圖得到: 地址,聯繫方式,營業時間。

如果您在Chrome瀏覽器中執行「右鍵單擊」,「查看源代碼」,您將看到這些值在HTML中本身不可用。


編輯

Sry基因保羅,我做了什麼,你告訴我,找到了admin-ajax.php,看到身體,但是,我真的現在卡住。

如何從json對象中檢索值並將其存儲到我自己的變量字段中?如果你能分享如何爲大衆和剛開始scrapy的人提供一個屬性,這將是一件好事。

這裏是我到目前爲止的代碼

Items.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) 

Sry基因長期編輯,所以在很短了,我怎麼保存json的價值到我的屬性?對於如

***項目[ '地址'] = *如何檢索****

PS,不知道這是否可以幫助,但我使用運行CMD線這些腳本

scrapy抓取麥當勞-o McDonalds.json -t json(將我的所有數據保存到json文件中)

我無法強調自己感到多麼感激。我知道這樣詢問你是不合理的,即使你沒有時間這樣也完全沒問題。

回答

18

(我張貼這scrapy-users郵件列表,但保羅的建議,因爲它補充與shell命令交互的答案,我在這裏張貼。)

一般來說,使用第三方服務網站呈現一些數據可視化(地圖,表格等)必須以某種方式發送數據,並且在大多數情況下,可以從瀏覽器訪問這些數據。

對於這種情況,檢查(即探索由瀏覽器發出的請求)顯示,數據是從POST請求加載到https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php

所以,基本上你有你在一個不錯的需要的數據json格式準備好消費。

Scrapy提供shell命令這是非常方便寫蜘蛛之前與網站思想家:

$ 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']) 
+0

Thx幫助Rho它的信息豐富,它的工作! *對於那些面臨同樣問題的人,請檢查這篇文章* – HeadAboutToExplode

7

當您在選擇的瀏覽器中打開https://www.mcdonalds.com.sg/locate-us/時,打開「檢查」工具(希望它有一個,例如Chrome或Firefox),然後查找「網絡」選項卡。

您可以進一步篩選「XHR」(XMLHttpRequest的)事件,你會看到一個POST請求https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php這身

action=ws_search_store_location&store_name=0&store_area=0&store_type=0 

到POST請求的響應是與所有的JSON對象信息你想

import json 
import pprint 
... 
class MySpider(BaseSpider): 
... 
    def parse_json(self, response): 

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

這將輸出類似:

{u'flagicon': u'https://www.mcdonalds.com.sg/wp-content/themes/mcd/images/storeflag.png', 
u'stores': {u'listing': [{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'}, 
          {u'address': u'383 Bukit Timah Road<br/>#01-09B<br/>Alocassia Apartments<br/>Singapore 259727', 
          u'city': u'Singapore', 
          u'id': 97, 
          u'lat': u'1.319752', 
          u'lon': u'103.827398', 
          u'name': u"McDonald's Alocassia", 
          u'op_hours': u'Daily: 0630-0100', 
          u'phone': u'68874961', 
          u'region': u'central', 
          u'type': [u'24hrs_weekend', 
            u'drive_thru', 
            u'mccafe'], 
          u'zip': u'259727'}, 

         ... 
          {u'address': u'60 Yishuan Avenue 4 <br/>#01-11<br/><br/>Singapore 769027', 
          u'city': u'Singapore', 
          u'id': 1036, 
          u'lat': u'1.423924', 
          u'lon': u'103.840628', 
          u'name': u"McDonald's Yishun Safra", 
          u'op_hours': u'24 hours', 
          u'phone': u'67585632', 
          u'region': u'north', 
          u'type': [u'24hrs', 
            u'drive_thru', 
            u'live_screening', 
            u'mccafe', 
            u'bday_party'], 
          u'zip': u'769027'}], 
      u'region': u'all'}} 

我會離開你去提取你想要的字段。

在FormRequest()你Scrapy送你可能需要添加一個「X-請求 - 由於:XMLHttpRequest的」頭(您的瀏覽器發送,如果你看一下請求頭中檢查工具)

+0

快回答! thx保羅,第二次你幫我:DDD – HeadAboutToExplode

+0

不客氣。這就是所有這一切:分享和幫助。 –

+0

凹凸,編輯。我能有更多的建議嗎? – HeadAboutToExplode