不一致的Scrapy Xpath行为(OS X + Linux)

时间:2014-01-23 18:37:41

标签: python linux macos xpath scrapy

我在Scrapy中遇到了Xpath选择器问题。每当我在OS X上运行蜘蛛时,选择器按预期工作;但是当我在Ubuntu 12.04和Raspbian中运行相同的脚本时,选择器不起作用。我不知道为什么会发生这种情况。

选择器是:

sel.xpath('//table[@class="times"]')

返回表的2个选择器给我,但是当我更进一步并添加一个索引来选择返回的第二个表时:

sel.xpath('//table[@class="times"][2]')

OS X将第二个表返回给我没问题,而Ubuntu / Raspbian则不返回任何内容:[]

我完全不知道为什么会这样。我已尽力复制环境(scrapy版本0.20,python 2.7),但我仍然没有想到它。作为参考,我试图通过shell抓取的页面是

scrapy shell "http://washington.dc.gegov.com/webadmin/dhd_431/lib/mod/inspection/paper/_paper_food_inspection_report.cfm?inspectionID=200651&wgdmn=431&wguid=1367&wgunm=sysact"

感谢有关此事的任何帮助。

1 个答案:

答案 0 :(得分:2)

使用//table[@class="times"][2]时要小心:它会选择所有后代第二个子表格元素,其父元素的类别为“times”。因此,如果一个节点只有一个类为“times”的子表,则该节点不匹配。

它与(//table[@class="times"])[2]不同,它会在根节点下为您提供第二个类“times”的表(这可能就是您想要的)。您也可以使用/descendant::table[@class="times"][2]

它仍然不同于//table[2][@class="times"],它选择所有后代表元素,它们是父元素的第二个子元素,并且具有类“times”。

请参阅XPath 1.0 specifications缩写语法//

  

注意:位置路径// para 1与位置路径/ descendant :: para 1的含义不同。后者选择第一个后代para元素;前者选择所有后代的para元素,这些元素是他们父母的第一个孩子。

让我们用scrapy shell会话来说明

paul@wheezy:~$ scrapy shell "http://washington.dc.gegov.com/webadmin/dhd_431/lib/mod/inspection/paper/_paper_food_inspection_report.cfm?inspectionID=200651&wgdmn=431&wguid=1367&wgunm=sysact"

In [1]: sel.xpath('//table[@class="times"][2]')
Out[1]: []

In [2]: sel.xpath('(//table[@class="times"])[2]')
Out[2]: [<Selector xpath='(//table[@class="times"])[2]' data=u'<table class="times" style="font-size:9p'>]

In [3]: sel.xpath('/descendant-or-self::table[@class="times"]')
Out[3]: 
[<Selector xpath='/descendant-or-self::table[@class="times"]' data=u'<table class="times" style="margin-top:1'>,
 <Selector xpath='/descendant-or-self::table[@class="times"]' data=u'<table class="times" style="font-size:9p'>]

In [4]: sel.xpath('/descendant-or-self::table[@class="times"][2]')
Out[4]: [<Selector xpath='/descendant-or-self::table[@class="times"][2]' data=u'<table class="times" style="font-size:9p'>]

In [5]: sel.xpath('/descendant::table[@class="times"][2]')
Out[5]: [<Selector xpath='/descendant::table[@class="times"][2]' data=u'<table class="times" style="font-size:9p'>]

In [6]: 

另外,在您的示例页面中,我看到4个表在其class属性中包含“times”:

  • <table class="times" style="margin-top:1...
  • <table class="times" style="font-size:9p...
  • <table class="times pt6" cellpadding="0"...
  • <table class="times fs_10px" style="bord...

所以请记住,[@class="times"]谓词意味着类属性恰好是“时间”,而不是简单地包含“时间”(您可以使用[contains(@class, "times")]