使用lxml和xpath读取网页

时间:2016-01-09 22:32:38

标签: python-2.7 xpath lxml urllib2

我试图从PredictIt获得一些市场的最新价格。例如,唐纳德特朗普将赢得2016年共和党总统候选人提名吗?"在https://www.predictit.org/contract/838/找到的市场我特别想要的文字是" 最新价格:?? "

Chrome告诉我xpath是/ html / body / div [7] / div / div [2] / div [2] / p [1] / strong / text()

import urllib2
url = 'https://www.predictit.org/Contract/838/'
page = urllib2.urlopen(url)
date = page.read()

from lxml import html
etree = html.fromstring(data)
price = etree.xpath('/html/body/div[7]/div/div[2]/div[2]/p[1]/strong/text()')

一切似乎都好,但是

 print price

返回一个空列表。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

如果您可以依赖'Latest Price'标记内的字符串<strong>,那么您可以使用:

In [305]: root.xpath('//strong[contains(text(), "Latest Price:")]/text()')
Out[305]: ['Latest Price: 34']

或者,或许更强大,您可以搜索所有<p>代码及其后代以查找包含字符串'Latest Price'的文字:

In [312]: root.xpath('//p/descendant-or-self::*[contains(text(), "Latest Price")]/text()')
Out[312]: ['Latest Price: 34']
import urllib2
url = 'https://www.predictit.org/Contract/838/'
page = urllib2.urlopen(url)
data = page.read()

import lxml.html as LH
root = LH.fromstring(data)
price = None
for text in root.xpath('//p/descendant-or-self::*[contains(text(), "Latest Price:")]/text()'):
    price = float(text.split(':', 1)[-1])

print(price)
# 35

XPath /html/body/div[7]/div/div[2]/div[2]/p[1]/strong/text()可能失败的原因是因为从urllib2.urlopen(url).read()收到的HTML可能与Chrome收到的HTML不同。 Chrome的浏览器会处理可能会更改DOM的JavaScript。 urllib2不会处理JavaScript。如果您在执行JavaScript后需要DOM,那么您需要一个像Selenium而不是urllib2的自动浏览器。令人高兴的是,在这种情况下,您正在寻找的内容不是由JavaScript提供的。但是,过于具体的XPath(例如/html/body/div[7]/div/div[2]/div[2]/p[1]/strong/text())可能会让您失望。

使用urllib2返回的HTML,似乎只有6个<div>代码:

In [315]: root.xpath('/html/body/div')
Out[315]: 
[<Element div at 0x7f0bd63632b8>,
 <Element div at 0x7f0bd6363310>,
 <Element div at 0x7f0bd6363368>,
 <Element div at 0x7f0bd63633c0>,
 <Element div at 0x7f0bd6363418>,
 <Element div at 0x7f0bd6363470>]

尝试访问第7个<div>标记会产生一个空列表:

In [316]: root.xpath('/html/body/div[7]')
Out[316]: []