lxml 及 HtmlElement

.attrib 屬性和 .get()方法

前者是html tag的屬性集合禽最,以字典表示;后者是取得某個屬性的值袱饭,相當于字典的.get()方法川无。看示例:

In [35]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')

In [37]: doc.attrib
Out[37]: {'class': 'post', 'id': '123'}

In [38]: doc.get('class')
Out[38]: 'post'
.drop_tag()方法

移除該html tag虑乖,但保留它的子節(jié)點和文本并合并到該tag的父節(jié)點懦趋。

In [46]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
In [47]: doc.find('.//p').drop_tag()

In [48]: lxml.html.tostring(doc)
Out[48]: b'<div class="post" id="123">abc<a href="/to-go">link</a></div>'
.drop_tree()方法   ('.//p')

移除該節(jié)及其子節(jié)點和文本,而它后面的文本(tail text)合并到前面一個節(jié)點或父節(jié)點疹味。

In [50]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
In [51]: doc.find('.//p').drop_tree()

In [52]: lxml.html.tostring(doc)
Out[52]: b'<div class="post" id="123"></div>'
.drop_tree()方法

移除該節(jié)及其子節(jié)點和文本仅叫,而它后面的文本(tail text)合并到前面一個節(jié)點或父節(jié)點。

In [50]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
In [51]: doc.find('.//p').drop_tree()

In [52]: lxml.html.tostring(doc)
Out[52]: b'<div class="post" id="123"></div>'
通過path(Xpath)或tag查找特定節(jié)點佛猛,前者返回找到的第一個惑芭,第二個返回找到的全部HTMLElement,第三個返回找到的第一個的節(jié)點的文本(.text)

In [55]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')

In [56]: doc.find('p')
Out[56]: <Element p at 0x7fc40a4dd6d8>

In [57]: doc.find('.//a')
Out[57]: <Element a at 0x7fc409fee4a8>

In [58]: doc.findall('p')
Out[58]: [<Element p at 0x7fc40a4dd6d8>]

In [76]: doc.findtext('.//a')
Out[76]: 'link'

.find_class(class_name)方法

通過class名稱查找所有含有class_name的元素继找,返回HtmlElement的列表

In [70]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p><p class="para p2"></p></div>')

In [71]: doc.find_class('para')
Out[71]: [<Element p at 0x7fc40a3ff278>, <Element p at 0x7fc40a3ffc78>]

.get_element_by_id(id) 方法

得到第一個id為輸入id的節(jié)點遂跟。如果有多個相同id的節(jié)點(按道理講,一個HTML文檔里面的id是唯一的)只返回第一個婴渡。

In [79]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')

In [80]: doc.get_element_by_id('123')
Out[80]: <Element div at 0x7fc409fda2c8>
.getchildren()幻锁、getparent() 方法

顧名思義,獲取 孩子節(jié)點和父節(jié)點边臼。需要注意的是哄尔,還是可以有多個(返回list),父親只有一個柠并。

In [83]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')

In [84]: doc.getchildren()
Out[84]: [<Element p at 0x7fc410836b38>]

In [85]: doc.getparent()
Out[85]: <Element body at 0x7fc40a3ff9a8>
# 注意:輸入的本沒有body岭接,div已經(jīng)是最上層節(jié)點富拗,它的父節(jié)點就是body了
.getnext() .getprevious() 方法

獲取后一個或前一個節(jié)點,如果沒有則返回None鸣戴。

In [109]: doc = lxml.html.fromstring('<div><p>abc</p><p>xyz</p></div>')
In [110]: doc.getnext()

In [111]: doc.find('p').getnext()
Out[111]: <Element p at 0x7fc409fdad68>

In [112]: doc.find('p').getprevious()
.getiterator()啃沪、.iter() 方法

從該節(jié)點開始,按文檔順序(深度優(yōu)先)遍歷所有子節(jié)點窄锅〈辞В可以指定只遍歷某些tag。

In [127]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
In [128]: for itr in doc.getiterator():
     ...:     print(itr.tag)
     ...: 
div
p
a
In [129]: for itr in doc.iter():
     ...:     print(itr.tag)
     ...: 
div
p
a
.iterchildren() 方法

只遍歷子節(jié)點入偷。

.iterancestors() .iterdescendants()方法

前者遍歷前輩(從父親節(jié)點開始)追驴,后者遍歷后輩(從子輩開始),都跳過該節(jié)點疏之。

In [134]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')

In [135]: a = doc.find('.//a')

In [136]: for itr in doc.iterancestors():
     ...:     print(itr.tag)
     ...: 
body
html

In [137]: for itr in a.iterancestors():
     ...:     print(itr.tag)
     ...: 
p
div
body
html

In [138]: for itr in doc.iterdescendants():
     ...:     print(itr.tag)
     ...: 
p
a
.iterfind(path) 方法

遍歷所有符合path的子節(jié)點殿雪,類似于findall()
.make_links_absolute(base_url)

很多網(wǎng)頁的鏈接都是類似href=”/path/a.html”沒有寫全網(wǎng)址,這個方法的作用就是補全網(wǎng)址体捏。
.tag 屬性

該節(jié)點的html tag 名稱
.text  and  .tail 屬性

都是該節(jié)點的文本內(nèi)容冠摄,不同的是一個在tag內(nèi),一個在尾部:

<p>text</p>tail
再看下面的代碼

In [173]: doc = lxml.html.fromstring('<div><p class="para">abc<a href="/to-go">link</a>worod</p>apple</div>')

In [174]: p = doc.find('p')

In [175]: p.text
Out[175]: 'abc'

In [176]: p.tail
Out[176]: 'apple'

.text_content() 方法

返回給節(jié)點及其子節(jié)點包含的所有文本

In [178]: doc.text_content()
Out[178]: 'abclinkworodapple'
lxml.html 從html字符串生成文檔樹結(jié)構(gòu)

我們下載得到的網(wǎng)頁就是一串html字符串几缭,如何把它輸入給lxml.html模塊河泳,從而生成html文檔的樹結(jié)構(gòu)呢?
該模塊提供了幾種不同的方法:

parse(filename_url_or_file):
輸入的是一個文件名年栓、URL或文件對象(有read()方法)拆挥。
document_fromstring(string):
輸入的是一個html的字符串,創(chuàng)建一個HTML文檔樹結(jié)構(gòu)某抓,它的根節(jié)點就是, 和 子節(jié)點纸兔。
fragment_fromstring(string, create_parent=False):
返回輸入字符串的HTML片段。這個片段壁紙只含有一個element(元素)否副,也就是單一節(jié)點汉矿,除非給出了create_parent 參數(shù),否則會報錯备禀。
fragments_fromstring(string):
返回包含輸入字符串中所有片段的列表洲拇。
fromstring(string):
返回值依據(jù)輸入字符串而定,如果輸入看起來像是一個文檔曲尸,則返回document_fromstring(string)赋续,如果是一個單一片段,則返回fragment_fromstring(string)另患。
下面我們通過具體示例來說明上面幾個方法的不同纽乱。

document_fromstring 的使用方法

In [1]: import lxml.html  as lh

In [2]: z = lh.document_fromstring('<span>abc</span><span>xyz</span>')
# 可以看到,它自動加了根節(jié)點<html>
In [3]: z
Out[3]: <Element html at 0x7fc410667b88>

In [4]: z.tag
Out[4]: 'html'
# 還加了<body>節(jié)點
In [5]: z.getchildren()
Out[5]: [<Element body at 0x7fc4101a3ae8>]
# 把字符串的兩個節(jié)點放在了<body>里面
In [6]: z.getchildren()[0].getchildren()
Out[6]: [<Element span at 0x7fc410092bd8>, <Element span at 0x7fc410667c28>]
fragment_fromstring 的使用

In [11]: z = lh.fragment_fromstring(‘<div>abc</div><div>xyz</div>’)
---------------------------------------------------------------------------
ParserError                               Traceback (most recent call last)
<ipython-input-11-a11f9a0f71d1> in <module>()
----> 1 z = lh.fragment_fromstring(‘<div>abc</div><div>xyz</div>’)

~/.virtualenvs/py3.6/lib/python3.6/site-packages/lxml/html/__init__.py in fragment_fromstring(html, create_parent, base_url, parser, **kw)
    850         raise etree.ParserError(
    851             “Multiple elements found (%s)”
--> 852             % ‘, ‘.join([_element_name(e) for e in elements]))
    853     el = elements[0]
    854     if el.tail and el.tail.strip():
ParserError: Multiple elements found (div, div)
# 可以看到昆箕,輸入是兩個節(jié)點(element)時就會報錯
# 如果加上 create_parent 參數(shù)鸦列,就沒問題了
In [12]: z = lh.fragment_fromstring('<div>abc</div><div>xyz</div>', create_parent='p')

In [13]: z.tag
Out[13]: 'p'

In [14]: z.getchildren()
Out[14]: [<Element div at 0x7fc40a41a818>, <Element div at 0x7fc40a41aea8>]

fragments_fromstring 的使用

# 輸入字符串含有一個節(jié)點租冠,則返回包含這一個節(jié)點的列表
In [17]: lh.fragments_fromstring('<div>abc</div>')
Out[17]: [<Element div at 0x7fc40a124ea8>]

# 輸入字符串含有多個節(jié)點,則返回包含這多個節(jié)點的列表
In [18]: lh.fragments_fromstring('<div>abc</div><div>xyz</div>')
Out[18]: [<Element div at 0x7fc40a124b88>, <Element div at 0x7fc40a124f98>]
fromstring 的使用


In [27]: z = lh.fromstring('<div>abc</div><div>xyz</div>')

In [28]: z
Out[28]: <Element div at 0x7fc40a0eb368>

In [29]: z.getchildren()
Out[29]: [<Element div at 0x7fc410135548>, <Element div at 0x7fc40a0eb2c8>]

In [30]: type(z)
Out[30]: lxml.html.HtmlElement

這里薯嗤,fromstring輸入的如果是多個節(jié)點肺稀,它會給加一個父節(jié)點并返回。但是像html網(wǎng)頁都是從節(jié)點開始的应民,我們使用fromstring() 和 document_fromstring() 都可以得到完整的網(wǎng)頁結(jié)構(gòu)。

從上面代碼中我們可以看到夕吻,那幾個函數(shù)返回的都是HtmlElement對象

from : https://www.yuanrenxue.com/crawler/extract-data-lxml-xpath.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诲锹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子涉馅,更是在濱河造成了極大的恐慌归园,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稚矿,死亡現(xiàn)場離奇詭異庸诱,居然都是意外死亡,警方通過查閱死者的電腦和手機晤揣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門桥爽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昧识,你說我怎么就攤上這事钠四。” “怎么了跪楞?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵缀去,是天一觀的道長。 經(jīng)常有香客問我甸祭,道長缕碎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任池户,我火速辦了婚禮咏雌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘煞檩。我一直安慰自己处嫌,他們只是感情好,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布斟湃。 她就那樣靜靜地躺著熏迹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凝赛。 梳的紋絲不亂的頭發(fā)上注暗,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天坛缕,我揣著相機與錄音,去河邊找鬼捆昏。 笑死赚楚,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的骗卜。 我是一名探鬼主播宠页,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼寇仓!你這毒婦竟也來了举户?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤遍烦,失蹤者是張志新(化名)和其女友劉穎俭嘁,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體服猪,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡供填,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了罢猪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片近她。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖坡脐,靈堂內(nèi)的尸體忽然破棺而出泄私,到底是詐尸還是另有隱情,我是刑警寧澤备闲,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布晌端,位于F島的核電站,受9級特大地震影響恬砂,放射性物質(zhì)發(fā)生泄漏咧纠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一泻骤、第九天 我趴在偏房一處隱蔽的房頂上張望漆羔。 院中可真熱鬧,春花似錦狱掂、人聲如沸演痒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸟顺。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間讯嫂,已是汗流浹背蹦锋。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留欧芽,地道東北人莉掂。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像千扔,于是被迫代替她去往敵國和親憎妙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344