使用lxml和Xpath刮取元素

时间:2015-03-18 15:22:29

标签: python xpath web-scraping lxml

我遇到的问题是要清除元素本身。我能够刮掉前两个(IncidentNbr和DispatchTime),但我无法获得地址...(1300 Dunn Ave)我希望能够刮掉那个元素,但也有足够的动态,所以我实际上并没有解析" 1300 Dunn Ave"我正在解析该元素。这是源代码

<td><span id="lstCallsForService_ctrl0_lblIncidentNbr">150318182198</span></td>
<td><nobr><span id="lstCallsForService_ctrl0_lblDispatchTime">3-18 10:25</span></nobr></td>
<td>
    <a id="lstCallsForService_ctrl0_lnkAddress" href="https://maps.google.com/?q=1300 DUNN AVE, Jacksonville, FL" target="_blank" style="text-decoration:underline;">1300 DUNN AVE</a>
</td>

这是我的代码:

from lxml import html
import requests

page = requests.get('http://callsforservice.jaxsheriff.org/')
tree = html.fromstring(page.text)

callSignal = tree.xpath('//span[@id="lstCallsForService_ctrl0_lblIncidentNbr"]/text()')
dispatchTime = tree.xpath('//span[@id="lstCallsForService_ctrl0_lblDispatchTime"]/text()')
location = tree.xpath('//span[@id="lstCallsForService_ctrl0_lnkAddress"]/text()')



print 'Call Signal: ', callSignal
print "Dispatch Time: ", dispatchTime
print "Location: ", location

这是我的输出:

Call Signal:  ['150318182198']
Dispatch Time:  ['3-18 10:25']
Location:  []

关于如何清理地址的任何想法?

2 个答案:

答案 0 :(得分:2)

这是您正在寻找的元素:

<a id="lstCallsForService_ctrl0_lnkAddress"
   href="https://maps.google.com/?q=1300 DUNN AVE, Jacksonville, FL"
   target="_blank" style="text-decoration:underline;">1300 DUNN AVE</a>

如您所见,它不是span元素。您当前的XPath表达式:

//span[@id="lstCallsForService_ctrl0_lnkAddress"]/text()

正在寻找具有此ID的span元素,而实际应该选择a元素。使用

//a[@id="lstCallsForService_ctrl0_lnkAddress"]/text()

代替。然后,结果应该是

Location:  ['1300 DUNN AVE']

请阅读alecxe的回答,其中有比我更实际的建议。

答案 1 :(得分:2)

首先,它是a元素,而不是span。在text()

之前需要一个双斜杠
//a[@id="lstCallsForService_ctrl0_lnkAddress"]//text()

为什么要出现双斜线?这是因为实际上这个a元素没有直接的文本节点子节点:

<a id="lstCallsForService_ctrl0_lnkAddress" href="https://maps.google.com/?q=5100 CLEVELAND RD, Jacksonville, FL" target="_blank">
    <u>5100 CLEVELAND RD</u>
</a>

您还可以通过u代码

来查看文字
//a[@id="lstCallsForService_ctrl0_lnkAddress"]/u/text()

此外,将解决方案扩展为多个结果:

  • 遍历表行
  • 每行使用contains()
  • 使用部分id属性匹配查找单元格值
  • 使用text_content()方法获取文字

实现:

for item in tree.xpath('//tr[@class="closedCall"]'):
    callSignal = item.xpath('.//span[contains(@id, "lblIncidentNbr")]')[0].text_content()
    dispatchTime = item.xpath('.//span[contains(@id, "lblDispatchTime")]')[0].text_content()
    location = item.xpath('.//a[contains(@id, "lnkAddress")]')[0].text_content()

    print 'Call Signal: ', callSignal
    print "Dispatch Time: ", dispatchTime
    print "Location: ", location
    print "------"

打印:

Call Signal:  150318182333
Dispatch Time:  3-18 11:22
Location:  9600 APPLECROSS RD
------
Call Signal:  150318182263
Dispatch Time:  3-18 11:12
Location:  1100 E 1ST ST
------
...