将从浏览器获取的 XPath 转换为 Scrapy 可用的 XPath

Convert the XPath gotten from browser to usable XPath for Scrapy

这是一个问题,我的浏览器总是无法获取特定的 XPath。

假设我想从 Google 图片搜索或 Pinterest 等网站提取所有图片。当我使用 Inspect element 然后使用 copy XPath 获取图像的 XPath 时,它会给我一些类似以下内容的信息:

//*[@id="rg_s"]/div[13]/a/img

我从 Google 搜索的图片中得到了这个。当我想在我的 spider 中使用它时,我将 SelectorHtmlXPathSelector 与以下 XPath 一起使用,但它们都不起作用!

//*[@id="rg_s"]/div/a/img
//div[@id="rg_s"]/div[13]/a/img
//[@class="rg_di rg_el"]/a/img #i change this based on the raw html of page 
#hxs.select(xpath).extract()
#Selector(response).xpath('xpath') 
.
.

我已经阅读了很多问题,但我找不到关于如何在 Scrapy 中使用从网络浏览器获取的 XPath 的一般答案。

通常盲目听从浏览器关于如何定位元素的建议是不安全可靠的。

首先,开发者工具生成的 XPath 表达式通常是绝对的 - 从所有父级的父级开始 - html 标签,这使得它更依赖于页面结构(好吧,firebug 也可以根据 id 属性做表达式)。

此外,由于网站页面加载的异步特性和 javascript 在浏览器中动态执行,您在浏览器中看到的 HTML 代码可能与 Scrapy 收到的代码有很大不同。 Scrapy 不是浏览器,"sees" 只是页面的初始 HTML 代码,在 "dynamic" 部分之前。

相反,检查 Scrapy 在响应中真正包含的内容:打开 Scrapy Shell,检查响应并调试您的 XPath 表达式和 CSS 选择器:

$ scrapy shell https://google.com
>>> response.xpath('//div[@id="myid"]')
...

这是我为 google 图片搜索得到的结果:

$ scrapy shell "https://www.google.com/search?q=test&tbm=isch&qscrl=1"
In [1]: response.xpath('//*[@id="ires"]//img/@src').extract()
Out[1]: 
[u'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRO9ZkSuDqt0-CRhLrWhHAyeyt41Z5I8WhOhTkGCvjiHmRiTSvDBfHKYjx_',
 u'https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQpwyzbW_qsRenDw3d4wwpwwm8n99ukMtLCVaPiTJxyviyQVBQeRCglVaY',
 u'https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSrxtoY3-3QHwhjc5Ofx8090uDYI8VOUbi3gUrd9USxZ-Vb1D5pAbOzJLMS',
 u'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTQO1A3dDJ07tIaFMHlXNOsOnpiY_srvHKJE1xOpsMZscjL3aKGxaGLOgru',
 u'https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQ71ukeTGCPLuClWd6MetTtQ0-0mwzo3rn1ug0MUnbpXmKnwNuuBnSWXHU',
 u'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRZmWrYR9A4W97jpjhtIbyUM5Lj3vRL0vgCKG_xfylc5wKFAk6UB8jiiKA',
 ...
 u'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRj08jK8sBjX90Tu1RO4BfZkKe5A59U0g1TpMWPFZlNnA70SQ5i5DMJkvV0']

从浏览器中的插入点生成的 XPath 注定是脆弱的,因为有许多不同的可能的 XPath 表达式可以到达任何给定的节点,JavaScript 可以修改 HTML,并且浏览器不知道你的意图。

对于你给出的例子,

//*[@id="rg_s"]/div[13]/a/img

第13个div特别容易破

请尝试找到更接近您的目标的独特识别特征。一个独特的 @id 属性是理想的,或者一个 @class 可以唯一标识您的目标或您的目标的近亲也可以很好地工作。

例如,对于 Google 图片搜索,类似于以下 XPath

//div[@id='rg_s']//img[@class='rg_i']"

将 select class rg_i 中包含搜索结果的 div 的所有图像。

如果您愿意放弃复制粘贴方法并学习足够的 XPath 来概括您的 selection,您将获得更好的结果。当然,标准免责声明也适用于需要更新抓取技术的演示更改。使用直接 API 调用会更加稳健(并且也是正确的)。