如何在缺少html标记时使用scrapy提取标签值列表

时间:2013-05-25 00:15:13

标签: python xpath scrapy

我目前正在使用

处理文档
<b> label1 </b>
value1 <br>
<b> label2 </b>
value2 <br>
....

我无法通过scrapy找出xpath的干净方法。 这是我最好的实现

hxs = HtmlXPathSelector(response)

section = hxs.select(..............)
values = section.select("text()[preceding-sibling::b/text()]"):
labels = section.select("text()/preceding-sibling::b/text()"):

但我不满意这种通过索引匹配两个列表的节点的方法。我宁愿遍历1个列表(值或标签)并将匹配的节点作为相对xpath进行查询。如:

values = section.select("text()[preceding-sibling::b/text()]"):
for value in values:
    value.select("/preceding-sibling::b/text()"):

我一直在调整这个表达式,但总是不返回匹配

更新

我正在寻找能够容忍“噪音”的稳健方法,例如:

garbage1<br>
<b> label1 </b>
value1 <br>
<b> label2 </b>
value2 <br>
garbage2<br>
<b> label3 </b>
value3 <br>
<div>garbage3</div>

1 个答案:

答案 0 :(得分:1)

编辑:抱歉,我使用lxml,但它对Scrapy自己的选择器也一样。

对于您提供的特定HTML,这将起作用:

>>> s = """<b> label1 </b>
... value1 <br>
... <b> label2 </b>
... value2 <br>
... """
>>> 
>>> import lxml.html
>>> lxml.html.fromstring(s)
<Element span at 0x10fdcadd0>
>>> soup = lxml.html.fromstring(s)
>>> soup.xpath("//text()")
[' label1 ', '\nvalue1 ', ' label2 ', '\nvalue2 ']
>>> res = soup.xpath("//text()")
>>> for i in xrange(0, len(res), 2):
...     print res[i:i+2]
... 
[' label1 ', '\nvalue1 ']
[' label2 ', '\nvalue2 ']
>>> 

编辑2:

>>> bs = etree.xpath("//text()[preceding-sibling::b/text()]")
>>> for b in bs:
...     if b.getparent().tag == "b":
...         print [b.getparent().text, b]
... 
[' label1 ', '\nvalue1 ']
[' label2 ', '\nvalue2 ']
[' label3 ', '\nvalue3 ']

另外,对于它的价值,如果你循环选择的元素,你想在for循环中的xpath中执行“./foo”,而不是“/ foo”。