我正在尝试查找此页面所有事件的URL:
https://www.eventshigh.com/delhi/food?src=exp
但是我只能看到JSON格式的URL:
{
"@context":"http://schema.org",
"@type":"Event",
"name":"DANDIYA NIGHT 2018",
"image":"https://storage.googleapis.com/ehimages/2018/9/4/img_b719545523ac467c4ad206c3a6e76b65_1536053337882_resized_1000.jpg",
"url":"https://www.eventshigh.com/detail/Delhi/5b30d4b8462a552a5ce4a5ebcbefcf47-dandiya-night-2018",
"eventStatus": "EventScheduled",
"startDate":"2018-10-14T18:30:00+05:30",
"doorTime":"2018-10-14T18:30:00+05:30",
"endDate":"2018-10-14T22:30:00+05:30",
"description" : "Dress code : TRADITIONAL (mandatory)\u00A0 \r\n Dandiya sticks will be available at the venue ( paid)\u00A0 \r\n Lip smacking food, professional dandiya Dj , media coverage , lucky draw \u00A0, Dandiya Garba Raas , Shopping and Games .\u00A0 \r\n \u00A0 \r\n Winners\u00A0 \r\n \u00A0 \r\n Best dress ( all",
"location":{
"@type":"Place",
"name":"K And L Community Hall (senior Citizen Complex )",
"address":"80 TO 49, Pocket K, Sarita Vihar, New Delhi, Delhi 110076, India"
},
这里是:
"url":"https://www.eventshigh.com/detail/Delhi/5b30d4b8462a552a5ce4a5ebcbefcf47-dandiya-night-2018"
但是我找不到包含链接的任何其他HTML / XML标签。我也找不到包含链接的相应JSON文件。您能帮我抓取此页面所有事件的链接吗?
https://www.eventshigh.com/delhi/food?src=exp
答案 0 :(得分:0)
从这样一个基于JavaScript的页面收集信息,乍一看可能令人生畏;但是实际上,由于所有信息都集中在一个地方,而不是分散在许多昂贵的HTTP请求查询中,因此通常可以提高生产力。
因此,当页面向您提供这样的JSON数据时,您可以通过对服务器友好并使用它来感谢他们! :)
您已经花了一些时间来进行“源视图分析”,这比尝试通过(昂贵的)Selenium / Splash / ect.-renderpipe获取信息要有效。
实现该目标的宝贵工具是 XPath 。有时可能需要我们的朋友regex
的一点额外帮助。
假设您已成功获取页面,并拥有一个Scrapy response
对象(或者您在另外收集的响应正文上有一个Parsel.Selector()
),则可以访问xpath()
方法为response.xpath
或selector.xpath
:
>>> response.status
200
您已经确定数据以纯文本(json)的形式存在,因此我们需要向下钻取至其隐藏位置,以最终提取原始JSON内容。
之后,将其转换为Python字典以进一步使用将是微不足道的。
在这种情况下,它位于容器节点<script type="application/ld+json">
中。我们的XPath可能如下所示:
>>> response.xpath('//script[@type="application/ld+json"]')
[<Selector xpath='//script[@type="application/ld+json"]' data='<script type="application/ld+json">\n{\n '>,
<Selector xpath='//script[@type="application/ld+json"]' data='<script type="application/ld+json">\n{\n '>,
<Selector xpath='//script[@type="application/ld+json"]' data='<script type="application/ld+json">\n '>]
这将在xml页面中找到每个“脚本” 节点,该节点的属性为“类型”,且 value 为“ application / ld” + json”。
显然,这还不够具体,因为我们发现了三个节点(Selector
包装在返回的列表中)。
根据您的分析,我们知道JSON必须包含"@type":"Event"
,因此让我们的xpath为此进行一些子字符串搜索:
>>> response.xpath("""//script[@type="application/ld+json"]/self::node()[contains(text(), '"@type":"Event"')]""")
[<Selector xpath='//script[@type="application/ld+json"]/self::node()[contains(text(), \'"@type":"Event"\')]' data='<script type="application/ld+json">\n '>]
在这里,我们添加了第二个限定符,该限定符表示我们的script
节点必须包含给定的 text 。
('self :: node()'显示了一些XPath轴魔术,可以在此时参考到我们当前的script
节点-而不是其后代。不过,我们将对此进行简化。)
现在,我们的返回列表包含一个节点/选择器。从data=
字符串中可以看出,如果要extract()
,现在
得到诸如<script type="application/ld+json">[...]</script>
之类的字符串。
由于我们关心的是节点的内容,而不是节点本身,因此,我们还有一步:
>>> response.xpath("""//script[@type="application/ld+json"][contains(text(), '"@type":"Event"')]/text()""")
[<Selector xpath='//script[@type="application/ld+json"][contains(text(), \'"@type":"Event"\')]/text()' data='\n [\n \n \n '>]
这将返回目标SelectorList
中的text()
。如您所见,我们也可以取消自我参照。
现在,xpath()
总是返回一个SelectorList
,但是我们为此提供了一些帮助:response.xpath().extract_first()
将在处理列表之前获取列表的第一个元素-检查它是否存在。
我们可以将结果放入data
变量中,然后将json.loads(data)
放入Python字典中并查看我们的值很简单:
>>> events = json.loads(data)
>>> [item['url'] for item in events]
['<url>',
'<url>',
'<url>',
'<url>']
现在,您可以将它们变成scrapy.Request(url)
了,您将知道如何从那里继续。
。
一如既往,负责任地进行爬网,并保持'net是一个不错的地方。我不认可任何非法行为。
评估自己的权利或获得访问指定目标资源的许可是自己的责任。