使用lxml xpath解析

问题描述 投票:0回答:3

我试图实现一个

lxml, xpath
代码来解析链接中的html:
https://www.theice.com/productguide/ProductSpec.shtml?specId=251
具体来说,我试图解析页面末尾附近的
<tr class="last">
表。

我想获取该子表中的文本,例如:“纽约”及其旁边列出的时间(对伦敦和新加坡执行相同的操作)。

我有以下代码(无法正常工作):

doc = lxml.html.fromstring(page)
tds = doc.xpath('//table[@class="last"]//table[@id"tradingHours"]/tbody/tr/td/text()')

配上美丽的汤:

table = soup.find('table', attrs={'id':'tradingHours'})
for td in table.findChildren('td'):
    print td.text

实现这一目标的最佳方法是什么?我想使用

lxml
而不是
beautifulSoup
(只是为了看看区别)。

python parsing lxml
3个回答
5
投票

您的

lxml
代码非常接近工作。主要问题是
table
标签不是具有
class="last"
属性的标签。相反,它是一个具有该属性的
tr
标签:

</tr><tr class="last"><td>TRADING HOURS</td>&#13;

因此,

//table[@class="last"]

没有匹配项。还有一个小语法错误:

@id"tradingHours"
应该是
@id="tradingHours"

您也可以完全省略

//table[@class="last"]
,因为
table[@id="tradingHours"]
足够具体。


与 BeautifulSoup 代码最接近的模拟是:

import urllib2
import lxml.html as LH

url = 'https://www.theice.com/productguide/ProductSpec.shtml?specId=251'
doc = LH.parse(urllib2.urlopen(url))
for td in doc.xpath('//table[@id="tradingHours"]//td/text()'):
    print(td.strip())

grouper Recipe

zip(*[iterable]*n)
,在解析表时通常非常有用。它将
iterable
中的项目收集到
n
项目组中。我们可以在这里使用它,如下所示:

texts = iter(doc.xpath('//table[@id="tradingHours"]//td/text()'))
for group in zip(*[texts]*5):
    row = [item.strip() for item in group]
    print('\n'.join(row))
    print('-'*80)

我不太擅长解释石斑鱼食谱的工作原理,但我在这里做了尝试


此页面正在使用 JavaScript 重新格式化日期。要在 JavaScript 更改内容后抓取页面,您可以使用 selenium:

import urllib2 import lxml.html as LH import contextlib import selenium.webdriver as webdriver url = 'https://www.theice.com/productguide/ProductSpec.shtml?specId=251' with contextlib.closing(webdriver.PhantomJS('phantomjs')) as driver: driver.get(url) content = driver.page_source doc = LH.fromstring(content) texts = iter(doc.xpath('//table[@id="tradingHours"]//td/text()')) for group in zip(*[texts]*5): row = [item.strip() for item in group] print('\n'.join(row)) print('-'*80)
产量

NEW YORK 8:00 PM-2:15 PM * 20:00-14:15 7:30 PM 19:30 -------------------------------------------------------------------------------- LONDON 1:00 AM-7:15 PM 01:00-19:15 12:30 AM 00:30 -------------------------------------------------------------------------------- SINGAPORE 8:00 AM-2:15 AM * 08:00-02:15 7:30 AM 07:30 --------------------------------------------------------------------------------
请注意,在这种特殊情况下,如果您不想使用 selenium,您可以使用 

pytz 自己解析和转换时间:

import dateutil.parser as parser import pytz text = 'Tue Jul 30 20:00:00 EDT 2013' date = parser.parse(text) date = date.replace(tzinfo=None) print(date.strftime('%I:%M %p')) # 08:00 PM ny = pytz.timezone('America/New_York') london = pytz.timezone('Europe/London') london_date = ny.localize(date).astimezone(london) print(london_date.strftime('%I:%M %p')) # 01:00 AM
    

1
投票
我喜欢 css 选择器,它比 xpath 更能适应页面变化:

import urllib from lxml import html url = 'https://www.theice.com/productguide/ProductSpec.shtml?specId=251' response = urllib.urlopen(url).read() h = html.document_fromstring(response) for tr in h.cssselect('#tradingHours tbody tr'): td = tr.cssselect('td') print td[0].text_content(), td[1].text_content()
    

1
投票
如果网站是正确的 html,id 属性是唯一的,您可以在

doc.get_element_by_id('tradingHours')

找到表格。

import urllib from lxml import html url = 'https://www.theice.com/productguide/ProductSpec.shtml?specId=251' response = urllib.urlopen(url).read() h = html.document_fromstring(response) print "BY ID" tradingHours = h.get_element_by_id('tradingHours') for tr in tradingHours.xpath('tbody/tr'): tds = tr.xpath('td') print tds[0].text.strip() for td in tds[1:]: print ' ', td.text.strip()

结果

BY ID NEW YORK Tue Jul 30 20:00:00 EDT 2013-Tue Jul 30 14:15:00 EDT 2013 * Tue Jul 30 19:30:00 EDT 2013 LONDON Tue Jul 30 20:00:00 EDT 2013-Tue Jul 30 14:15:00 EDT 2013 Tue Jul 30 19:30:00 EDT 2013 SINGAPORE Tue Jul 30 20:00:00 EDT 2013-Tue Jul 30 14:15:00 EDT 2013 * Tue Jul 30 19:30:00 EDT 2013
    
© www.soinside.com 2019 - 2024. All rights reserved.