Hea*_*ode 22 python screen-scraping scrapy
我scrapy
用来屏蔽网站上的数据.但是,我想要的数据不在html本身内部,而是来自javascript.所以,我的问题是:
如何获取此类案例的值(文本值)?
这是我试图筛选的网站:https: //www.mcdonalds.com.sg/locate-us/
我想要的属性:地址,联系方式,营业时间.
如果您在Chrome浏览器中执行"右键单击","查看源代码",您将看到HTML中无法使用此类值.
编辑
Sry paul,我做了你告诉我的事情,找到admin-ajax.php
并看到了身体但是,我现在真的被困住了.
如何从json对象中检索值并将其存储到我自己的变量字段中?如果您可以分享如何为公众和刚刚开始scrapy的人分享一个属性,那将是一件好事.
到目前为止,这是我的代码
Items.py
class McDonaldsItem(Item):
name = Field()
address = Field()
postal = Field()
hours = Field()
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
Sry进行长时间编辑,简而言之,我如何将json值存储到我的属性中?例如
***项目['地址'] =*如何检索****
PS,不确定这是否有帮助,但是,我使用cmd行运行这些脚本
scrapy crawl mcdonalds -o McDonalds.json -t json(将我的所有数据保存到json文件中)
我不能强调我的感激之情.我知道问你这个是不合理的,即使你没有时间这个也完全没问题.
Rol*_*Max 21
(我把它发布到了scrapy-users
邮件列表,但保罗的建议我在这里发布,因为它通过shell
命令交互补充了答案.)
通常,使用第三方服务呈现某些数据可视化(地图,表格等)的网站必须以某种方式发送数据,并且在大多数情况下,可以从浏览器访问这些数据.
对于这种情况,检查(即浏览浏览器发出的请求)显示数据从POST请求加载到https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php
所以,基本上你可以在一个漂亮的json格式中准备好消费所需的所有数据.
shell
在写蜘蛛之前,Scrapy提供了一个非常方便思考者的命令:
$ 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'}
Run Code Online (Sandbox Code Playgroud)
简而言之:在你的蜘蛛中你必须返回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'])
Run Code Online (Sandbox Code Playgroud)
当您在所选浏览器中打开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
Run Code Online (Sandbox Code Playgroud)
对该POST请求的响应是一个JSON对象,其中包含您需要的所有信息
import json
import pprint
...
class MySpider(BaseSpider):
...
def parse_json(self, response):
js = json.loads(response.body)
pprint.pprint(js)
Run Code Online (Sandbox Code Playgroud)
这将输出如下内容:
{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'}}
Run Code Online (Sandbox Code Playgroud)
我会留下你提取你想要的字段.
在使用Scrapy发送的FormRequest()中,您可能需要添加"X-Requested-With:XMLHttpRequest"标头(如果您查看检查工具中的请求标头,则您的浏览器会发送该标头)
归档时间: |
|
查看次数: |
18124 次 |
最近记录: |