在Scrapy中,为什么xpath表达式中的text()[n]后跟extract()不等于extract(),然后是选择[n-1]个元素?

问题描述:

我试图从http://www.apkmirror.com下载scrapy APK下载页面,但是我的一些XPath表达式没有按照我的预期行事。在Scrapy中,为什么xpath表达式中的text()[n]后跟extract()不等于extract(),然后是选择[n-1]个元素?

例如,在Scrapy壳为http://www.apkmirror.com/apk/google-inc/maps/maps-9-2-0-9-release/maps-9-2-0-android-4-3-902013124-android-apk-download/,我提取“APK细节”部分,如下所示:

In [1]: response.xpath('//*[@title="APK details"]/following-sibling::*[@class="appspec-value"]//text()').extract() 
Out[1]: 
[u'Version: 9.2.0 (902013124)', 
u'arm ', 
u'Package: com.google.android.apps.maps', 
u'\n', 
u'40,353 downloads '] 

我要提取的支持的体系结构,这是这种情况下'arm '在第二行。我提取由

In [2]: response.xpath('//*[@title="APK details"]/following-sibling::*[@class="appspec-value"]//text()[2]').extract() 
Out[2]: [u'arm '] 

行到目前为止,一切都很好,但也有其他的网页,如http://www.apkmirror.com/apk/htc-corporation/htc-backup/htc-backup-4-5-696121-release/htc-backup-4-5-696121-android-apk-download/其中包含版本的行不存在。在这种情况下,我得到

In [3]: response.xpath('//*[@title="APK details"]/following-sibling::*[@class="appspec-value"]//text()').extract() 
Out[3]: 
[u'Version: 4.5.696121 (454663465) ', 
u'Package: com.htc.backup', 
u'\n', 
u'1,664 downloads '] 

奇怪的是,如果我前面的XPath表达式后添加[2],我得到一个空行:

In [2]: response.xpath('//*[@title="APK details"]/following-sibling::*[@class="appspec-value"]//text()[2]').extract() 
Out[2]: [u'\n'] 

这相当于列表的第三个元素从extract()获得,而我期望它仍然是从Package:开始的第二行。

总之,好像我的假设,即“包括在XPath表达式[n]并呼吁extract()相当于调用extract()并从结果列表中选择[n-1]”是不正确的。有人可以证实这一点,并解释为什么不?

+0

'(// * [@ title =“APK详细信息”]/following-sibling :: * [@ class =“appspec-value”] // text())[2]'? – choroba

+0

如果我尝试'response.xpath('(// * [@ title =“APK details”]/following-sibling :: * [@ class =“appspec-value”] // text())[2] ').extract()',我得到一个'ValueError:所有的字符串必须是XML兼容的:Unicode或ASCII,没有NULL字节或控制字符。 –

拿这个XML为例:

<r> 
    <p id="1"> 
    <c>text 1</c> 
    <c>text 2</c> 
    <c>text 3</c> 
    </p> 
    <p id="2"> 
    <c>text 4</c> 
    <c>text 5</c> 
    <c><a>text 6</a><a>text 7</a></c> 
    </p> 
</r> 

//c//text()[1]回报text 1 - 6,因为他们都是低于c第一个文本。

//c//text()[2]回报text 7,因为它下面c唯一秒文本。

(//c//text())[2]回报text 2,因为它是下面的一些c所有文本的秒。

+0

在原始示例中,我注意到通过从XPath表达式中除去'// text()','extract()'结果中的不同列表项产生自自动关闭的'
'标记,该标记本身不会不包含'text()'。 –