您好,登錄后才能下訂單哦!
【前情回顧】如何靈活的解析網(wǎng)頁(yè),提取我們想要的數(shù)據(jù),是我們寫(xiě)爬蟲(chóng)時(shí)非常關(guān)心和需要解決的問(wèn)題。
從Python的眾多的可利用工具中,我們選擇了lxml的,它的好我們知道,它的妙待我們探討。前面我們已經(jīng)從HTML字符串轉(zhuǎn)換成的HtmlElement對(duì)象,接下來(lái)我們就探討該如何操作這個(gè)的HtmlElement對(duì)象。
這個(gè)的HtmlElement對(duì)象有各種方法,我們重點(diǎn)討論跟解析網(wǎng)頁(yè)相關(guān)的函數(shù),而修改這個(gè)對(duì)象的方法若與提取內(nèi)容相關(guān)也一并介紹,介紹過(guò)程結(jié)合下面這段HTML代碼以便更好說(shuō)明問(wèn)題:
<div class="post" id="123"> <p class="para">abc<a href="/to-go">link</a></p> </div>
前者是html tag的屬性集合,以字典表示;后者是取得某個(gè)屬性的值,相當(dāng)于字典的.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'
移除該html標(biāo)簽,但保留它的子節(jié)點(diǎn)和文本并合并到該標(biāo)簽的父節(jié)點(diǎn)。
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>'
移除該節(jié)及其子節(jié)點(diǎn)和文本,而它后面的文本(尾文)合并到前面一個(gè)節(jié)點(diǎn)或父節(jié)點(diǎn)。
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>'
通過(guò)路徑(Xpath的)或標(biāo)簽查找特定節(jié)點(diǎn),前者返回找到的第一個(gè),第二個(gè)返回找到的全部HTML元素,第三個(gè)返回找到的第一個(gè)的節(jié)點(diǎn)的文本(的.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'
通過(guò)類(lèi)名稱(chēng)查找所有含有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>]
得到第一個(gè)ID為輸入ID的節(jié)點(diǎn)。如果有多個(gè)相同ID的節(jié)點(diǎn)(按道理講,一個(gè)HTML文檔里面的ID是唯一的)只返回第一個(gè)。
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>
顧名思義,獲得孩子節(jié)點(diǎn)和父節(jié)點(diǎn)。需要注意的是,還是可以有多個(gè)(返回列表),父親只有一個(gè)。
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> # 注意:輸入的本沒(méi)有body,div已經(jīng)是最上層節(jié)點(diǎn),它的父節(jié)點(diǎn)就是body了
獲取后一個(gè)或前一個(gè)節(jié)點(diǎn),如果沒(méi)有則返回?zé)o。
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()
從該節(jié)點(diǎn)開(kāi)始,按文檔順序(深度優(yōu)先)遍歷所有子節(jié)點(diǎn)??梢灾付ㄖ槐闅v某些標(biāo)簽。
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
只遍歷子節(jié)點(diǎn)。
前者遍歷前輩(從父親節(jié)點(diǎn)開(kāi)始),后者遍歷后輩(從子輩開(kāi)始),都跳過(guò)該節(jié)點(diǎn)。
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
遍歷所有符合路徑的子節(jié)點(diǎn),類(lèi)似于的findall()
很多網(wǎng)頁(yè)的鏈接都是類(lèi)似HREF =” /路徑/ a.html”沒(méi)有寫(xiě)全網(wǎng)址,這個(gè)方法的作用就是補(bǔ)全網(wǎng)址。
該節(jié)點(diǎn)的html標(biāo)簽名稱(chēng)
都是該節(jié)點(diǎn)的文本內(nèi)容,不同的是一個(gè)在標(biāo)簽內(nèi),一個(gè)在尾部:
<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'
返回給節(jié)點(diǎn)及其子節(jié)點(diǎn)包含的所有文本
In [178]: doc.text_content() Out[178]: 'abclinkworodapple'
以上就是我們從網(wǎng)頁(yè)提取內(nèi)容時(shí)用到的主要屬性和方法。下一節(jié),我們將以實(shí)例講解具體提取數(shù)據(jù)的過(guò)程。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。