XPath返回空列表。为什么忽略目标div元素?

时间:2016-09-25 14:20:33

标签: python html xpath scrapy html-parsing

我是XPath和Scrapy的新手。我正在尝试定位一个没有唯一类的节点(即class="pubBody")。

已经尝试过: xpath not contains A and B

这应该是一个简单的任务,但XPath只是错过了第二项。我是从scrapy shell做的。在命令提示符下:

scrapy shell“http://www.sciencedirect.com/science/journal/00221694/

我正在寻找第二个div:

<div id="issueListHeader" class="pubBody">...< /div>

<div class="pubBody">... < /div> 

我只能得到第一个而不是第二个。类似问题的最佳答案建议尝试类似:

hxs.xpath('//div[contains(@class,"pubBody") and not(contains(@id,"issueListHeader"))]') 

但由于某种原因,这会返回一个空列表。有什么帮助吗?一定是想念一些傻事,我已经试了好几天了!

其他细节:

进入scrapy shell后:

import scrapy

xs = scrapy.Selector(response)

hxs.xpath('//div[@class="pubBody"]')

仅适用于第一个div元素:

[<Selector xpath='//div[@class="pubBody"]' data='<div id="issueListHeader" class="pubBody'>]

对于失败的第二个div元素,我也尝试过:

hxs.xpath('//div[@class="pubBody" and not(@id="issueListHeader")]').extract_first()

hxs.xpath('//div[starts-with(@class, "pubBody") and not(re:test(@id, "issueListHeader"))]')

还直接从Chrome中复制了XPath,但也返回'[]':

hxs.xpath('//*[@id="issueList"]/div/form/div[2]')

2 个答案:

答案 0 :(得分:1)

问题在于 HTML在此页面上的格式很差。为了演示,看看同样精确的CSS选择器如何使用Scrapy生成0结果并在BeautifulSoup中生成94:

In [1]: from bs4 import BeautifulSoup

In [2]: soup = BeautifulSoup(response.body, 'html5lib')  # note: "html5lib" has to be installed

In [3]: len(soup.select(".article h4 a"))
Out[3]: 94

In [4]: len(response.css(".article h4 a"))
Out[4]: 0

您尝试查找的pubBody元素也是如此:

In [6]: len(response.css(".pubBody"))
Out[6]: 1

In [7]: len(soup.select(".pubBody"))
Out[7]: 2

因此,请尝试连接BeautifulSoup以修复/清理HTML - 最好通过middleware

我已经创建了一个简单的scrapy_beautifulsoup middleware来轻松连接到项目中:

  • 通过pip安装:

    pip install scrapy-beautifulsoup
    
  • settings.py中配置中间件:

    DOWNLOADER_MIDDLEWARES = {
        'scrapy_beautifulsoup.middleware.BeautifulSoupMiddleware': 543
    }
    BEAUTIFULSOUP_PARSER = "html5lib" 
    

利润。

答案 1 :(得分:0)

我怀疑问题是您尝试解析的页面(http://www.sciencedirect.com/science/journal/00221694/)的源是无效的XML,因为<link ...>节点/元素/标签没有结束标记。可能还有其他问题,但这些问题是我发现的第一个问题。

我在Javascript上生锈了,但您可以尝试将DOM向下导航到页面中的较低级别(即。身体或更接近您尝试定位的元素的其他节点)然后执行XPath从那个层面。

更新:我刚刚尝试删除文档的<head>并将其传递给XML解析器,但它仍然在未关闭的服务器<input>节点上中断。除非我忘记一些特殊的JavaScript XML / XPath规则方法来消除结束标记,否则我怀疑你可能更适合使用像JQuery这样的东西找到你正在寻找的元素。