from lxml import *
import lxml.html
import urllib2
import lxml.html as H
import sys
if __name__ == '__main__':
ss = u"<html> <body> <form> <div id='leftmenu'> <h3>檔案</h3>\
<ul><!-- 找到這里 --></ul> </div> </form> </body> </html>"
ss = urllib2.urlopen("http://auto.qq.com/a/20090910/000052.htm").read()
doc = H.document_fromstring(ss)
nodes = doc.xpath("http://div[@id='ArticleTit']")
if nodes is not None:
#print nodes[0].text.encode(sys.getfilesystemencoding())
print nodes[0].text.encode(sys.getfilesystemencoding())
nodes = doc.xpath("http://div[@id='ArticleCnt']")
if nodes is not None:
print nodes[0].text_content().encode(sys.getfilesystemencoding())
#print nodes[0].text.encode(sys.getfilesystemencoding())
呵呵, 簡單高效. 之前用java寫了N長的代碼. 真是不爽.
參考: http://www.go4pro.org/?p=118
附錄:XPATH的簡單語法介紹
XPATH基本上是用一種類似目錄樹的方法來描述在XML文檔中的路徑。比如用“/”來作為上下層級間的分隔。第一個“/”表示文檔的根節(jié)點(注意,不是指文檔最外層的tag節(jié)點,而是指文檔本身)。比如對于一個HTML文件來說,最外層的節(jié)點應(yīng)該是”/html”。
同樣的,“..”和“.”分別被用來表示父節(jié)點和本節(jié)點。
XPATH返回的不一定就是唯一的節(jié)點,而是符合條件的所有節(jié)點。比如在HTML文檔里使用“/html/head/scrpt”就會把head里的所有script節(jié)點都取出來。
為了縮小定位范圍,往往還需要增加過濾條件。過濾的方法就是用“[”“]”把過濾條件加上。比如在HTML文檔里使用“/html/body/div[@id='main']”,即可取出body里id為main的div節(jié)點。
其中@id表示屬性id,類似的還可以使用如@name, @value, @href, @src, @class….
而 函數(shù)text()的意思則是取得節(jié)點包含的文本。比如:<div>hello<p>world</p>< /div>中,用”div[text()='hello']“即可取得這個div,而world則是p的text()。
函數(shù)position()的意思是取得節(jié)點的位置。比如“li[position()=2]”表示取得第二個li節(jié)點,它也可以被省略為“li[2]”。
不過要注意的是數(shù)字定位和過濾 條件的順序。比如“ul/li[5][@name='hello']”表示取ul下第五項li,并且其name必須是hello,否則返回空。而如果用 “ul/li[@name='hello'][5]”的意思就不同,它表示尋找ul下第五個name為”hello“的li節(jié)點。
此外,“*”可以代替所有的節(jié)點名,比如用”/html/body/*/span”可以取出body下第二級的所有span,而不管它上一級是div還是p或是其它什么東東。
而 “descendant::”前綴可以指代任意多層的中間節(jié)點,它也可以被省略成一個“/”。比如在整個HTML文檔中查找id為“leftmenu”的 div,可以用“/descendant::div[@id='leftmenu']”,也可以簡單地使用“ //div[@id='leftmenu']”。
至于“following-sibling::”前綴就如其名所說,表示同一層的下一個節(jié)點。”following-sibling::*”就是任意下一個節(jié)點,而“following-sibling::ul”就是下一個ul節(jié)點。
更復(fù)雜的XPATH語法還是請參考官文檔
《XML Path Language (XPath)》。