2013-07-30 102 views
1

我試圖實現lxml, xpath代碼來解析鏈接中的html:https://www.theice.com/productguide/ProductSpec.shtml?specId=251 具體來說,我試圖在接近頁面末尾時分析<tr class="last">表。使用lxml xpath解析

我想獲得該子表中的文本,例如:「紐約」和它旁邊列出的小時數(倫敦和新加坡也一樣)。

我有以下的代碼(不能正常工作):

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

隨着BeautifulSoup:

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

什麼是實現這一目標的最佳方法是什麼?我想用lxml而不是beautifulSoup(只是爲了看看區別)。

回答

3

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 recipezip(*[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) 

我不是在解釋石斑魚食譜是如何工作的非常好,但是我已經做了一個attempt here


此頁面正在使用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 
-------------------------------------------------------------------------------- 

注意,在這種特殊情況下,如果你不想使用硒,你可以使用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 
+0

謝謝,我正在尋找這樣的答案。是否有可能區分諸如「紐約」之類的城市和使用「xpath」的時代?例如,這個當前的'for'循環會打印所有內容,但是我想要在網站中挖掘結果:一個具有時間的城市。 –

+0

感謝以上,但有些不對。我得到的結果是:'星期二7月30日20:00:00美國東部時間2013年 - 星期二7月30日14:15:00美國東部時間2013年* 星期二7月30日19:30:00 EDT 2013'。這是同一時間,重複3次以上。另外它增加了額外的日期功能,我不確定它來自哪裏。它應該嚴格按照現場的時間。你知道這裏發生了什麼嗎?即使我使用「BS」,也是一樣的結果... –

+1

頁面正在使用JavaScript來更改HTML。 'urllib2.urlopen'在沒有任何JavaScript處理的情況下下載HTML。瀏覽器顯示JavaScript處理後的結果。要在JavaScript處理後刮掉頁面,您可以使用硒(參見上文)。 – unutbu

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