python解析庫(kù)

1. Beautiful Soup (bs4 )

Beautiful Soup 是一個(gè)可以從HTML或XML文件中提取數(shù)據(jù)的Python庫(kù).它能夠通過(guò)你喜歡的轉(zhuǎn)換器實(shí)現(xiàn)慣用的文檔導(dǎo)航,查找,修改文檔的方式.Beautiful Soup會(huì)幫你節(jié)省數(shù)小時(shí)甚至數(shù)天的工作時(shí)間.

在測(cè)試學(xué)習(xí)使用bs4的過(guò)程中,需要反復(fù)用到xml文檔。這里就采用bs4官方文檔中提供的一個(gè)html代碼。這是愛(ài)麗絲夢(mèng)游仙境中的一段內(nèi)容。

<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a  class="sister" id="link1">Elsie</a>,
<a  class="sister" id="link2">Lacie</a> and
<a  class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>

包含一個(gè)簡(jiǎn)單的頁(yè)面。
下面使用python做簡(jiǎn)單測(cè)試。首先是格式化輸出:

# 構(gòu)造BeautifulSoup 對(duì)象,其中html_doc為前文的愛(ài)麗絲夢(mèng)游仙境頁(yè)面
page = BeautifulSoup(html_doc, 'html.parser')
# 格式化輸出
print(page.prettify())

控制臺(tái)的輸出結(jié)果為:

<html>
 <head>
  <title>
   The Dormouse's story
  </title>
 </head>
 <body>
  <p class="title">
   <b>
    The Dormouse's story
   </b>
  </p>
  <p class="story">
   Once upon a time there were three little sisters; and their names were
   <a class="sister"  id="link1">
    Elsie
   </a>
   ,
   <a class="sister"  id="link2">
    Lacie
   </a>
   and
   <a class="sister"  id="link3">
    Tillie
   </a>
   ;
and they lived at the bottom of a well.
  </p>
  <p class="story">
   ...
  </p>
 </body>
</html>

顯然這是一個(gè)規(guī)范的html文件。使用起來(lái)實(shí)在是太方便了~再探索一下其他的功能吧。
bs4能夠很輕松地獲取到文檔信息,瀏覽結(jié)構(gòu)化信息。例如,獲取頁(yè)面的title,只需要

page.title.name

需要注意的是,如果使用CSS選擇器,應(yīng)該使用select方法,如:

#查找class為sister的
print('class為sister的(CSS方式查找的):', page.select('.sister'))
#查找id為link2的
print('id為link2的(CSS方式查找的:)', page.select('#link2'))

完整的測(cè)試代碼:


# 構(gòu)造BeautifulSoup 對(duì)象,其中html_doc為前文的愛(ài)麗絲夢(mèng)游仙境頁(yè)面
page = BeautifulSoup(html_doc, 'html.parser')
# 格式化輸出
# print(page.prettify())


# 獲取title相關(guān)信息
print('page.title : ', page.title)
print('page.title.name : ', page.title.name)
print('page.title.text : ', page.title.text)
print('page.title.parent.name : ', page.title.parent.name)

# 獲取a標(biāo)簽
print('單個(gè)a標(biāo)簽:', page.a)
print('所有a標(biāo)簽: ', page.find_all('a'))

# 以css的方式查找 使用select
print('class為sister的(CSS方式查找的):', page.select('.sister'))
print('id為link2的(CSS方式查找的:)', page.select('#link2'))

輸出結(jié)果為:

page.title :  <title>The Dormouse's story</title>
page.title.name :  title
page.title.text :  The Dormouse's story
page.title.parent.name :  head
單個(gè)a標(biāo)簽: <a class="sister"  id="link1">Elsie</a>
所有a標(biāo)簽:  [<a class="sister"  id="link1">Elsie</a>, <a class="sister"  id="link2">Lacie</a>, <a class="sister"  id="link3">Tillie</a>]
class為sister的(CSS方式查找的): [<a class="sister"  id="link1">Elsie</a>, <a class="sister"  id="link2">Lacie</a>, <a class="sister"  id="link3">Tillie</a>]
id為link2的(CSS方式查找的:) [<a class="sister"  id="link2">Lacie</a>]

如果要獲取標(biāo)簽中的某一部分,可以使用get方法。例如:獲取頁(yè)面中所有a標(biāo)簽的鏈接內(nèi)容。

for line in page.find_all('a'):
    print(line.get('href'))

輸出為:

http://example.com/elsie
http://example.com/lacie
http://example.com/tillie

如果要獲取頁(yè)面中所有的文字信息,只需要一行代碼:

text = page.get_text()

這是bs4一些最基礎(chǔ)的用法。遇到問(wèn)題就查一下官方文檔:bs4.4.0官方文檔

2. lxml

lxml是一個(gè)Python庫(kù),使用它可以輕松處理XML和HTML文件,還可以用于web爬取。市面上有很多現(xiàn)成的XML解析器,但是為了獲得更好的結(jié)果,開(kāi)發(fā)人員有時(shí)更愿意編寫(xiě)自己的XML和HTML解析器。這時(shí)lxml庫(kù)就派上用場(chǎng)了。這個(gè)庫(kù)的主要優(yōu)點(diǎn)是易于使用,在解析大型文檔時(shí)速度非常快,歸檔的也非常好,并且提供了簡(jiǎn)單的轉(zhuǎn)換方法來(lái)將數(shù)據(jù)轉(zhuǎn)換為Python數(shù)據(jù)類(lèi)型,從而使文件操作更容易。

2.1 Xpath語(yǔ)言

節(jié)點(diǎn):元素、屬性、文本、命名空間、文檔節(jié)點(diǎn)等。
節(jié)點(diǎn)關(guān)系:父、字、同胞、先輩、后代等。

表達(dá)式 描述
nodename 選此節(jié)點(diǎn)的所有子節(jié)點(diǎn)
// 從任意子節(jié)點(diǎn)選擇
/ 從根節(jié)點(diǎn)選擇(這里是相對(duì)的)
. 從當(dāng)前節(jié)點(diǎn)選擇
.. 從上一級(jí)節(jié)點(diǎn)選擇
@ 取屬性

2.2 lxml的使用

首先需要導(dǎo)入lxml庫(kù)

from lxml import etree
from bs4_sample import html_doc

構(gòu)造etree

et = etree.HTML(html_doc)

需要使用單個(gè)屬性獲取所需內(nèi)容

  • 變量.tag——標(biāo)簽名——字符串
  • 變量.attrib——節(jié)點(diǎn)標(biāo)簽a的屬性——字典
  • 變量.text——標(biāo)簽文本——字符串
    通過(guò)例子體會(huì):
et = etree.HTML(html_doc)
print(et)

for tag in et:
    print("TAG : ", et.tag)
for attrib in et:
    print("ATTRIB : ", et.attrib)
for text in et:
    print("TEXT : ", et.text)

輸出結(jié)果為:

TAG :  html
TAG :  html
ATTRIB :  {}
ATTRIB :  {}
TEXT :  None
TEXT :  None

也就是說(shuō),et變量實(shí)際上是這個(gè)html頁(yè)面的根節(jié)點(diǎn)。若執(zhí)行

print(et)

輸出的是

<Element html at 0x1a5b5135b40>

也就是html,也即該頁(yè)面的最外層:

html

測(cè)試代碼:

for i in range(len(et)):
    print(et[i].tag)

輸出結(jié)果為:

head
body

觀察頁(yè)面的結(jié)構(gòu),發(fā)現(xiàn)html下兩個(gè)同胞節(jié)點(diǎn)為head 和body。如圖:


頁(yè)面結(jié)構(gòu)

獲取各個(gè)子節(jié)點(diǎn)的信息,以類(lèi)似于多維數(shù)組的方式,通過(guò)代碼實(shí)現(xiàn)遍歷:

for i in range(len(et)):
    print(et[i].tag)
    for j in range(len(et[i])):
        print("      "+et[i][j].tag)

輸出結(jié)果為:

head
      title
body
      p
      p
      p

與頁(yè)面標(biāo)簽結(jié)構(gòu)相符。這樣就基本理解了etree.HTML(html_doc)語(yǔ)句所生成對(duì)象的結(jié)構(gòu)。

下面來(lái)做幾件爬蟲(chóng)可能需要的工作。

  • 檢查元素是都有子元素
  • 檢查節(jié)點(diǎn)是都為一個(gè)elements
  • 檢查一個(gè)元素是否有父元素
  • 檢查同胞元素
  • 尋找元素
    在python代碼中依次做這些測(cè)試。比較簡(jiǎn)單,基本方法總結(jié)見(jiàn)表:
功能 方法
檢查是否存在子元素 len(et)>0
檢查是否為element etree.iselement(et[i]))
檢查是否存在父元素 getparent() 注意:是方法 不是getparent屬性!
檢查同胞元素 getprevious()和getnext()方法
尋找元素 find()方法

代碼比較簡(jiǎn)單,測(cè)試結(jié)果寫(xiě)在注釋中:

# 1.檢查元素是都有子元素   ——檢查長(zhǎng)度
#   1.1 檢查根節(jié)點(diǎn)是否有子元素
if len(et) > 0:
    print("根節(jié)點(diǎn)有%s個(gè)子元素" % len(et))
else:
    print("根節(jié)點(diǎn)沒(méi)有子元素!")
#   1.2檢查根節(jié)點(diǎn)的子節(jié)點(diǎn)是否有子元素
for i in range(len(et)):
    if len(et[i]) > 0:
        print("%s標(biāo)簽有子節(jié)點(diǎn),第一個(gè)子節(jié)點(diǎn)為:%s" % (et[i].tag, et[i][0].tag))
    else:
        print("%s標(biāo)簽沒(méi)有子節(jié)點(diǎn)!" % et[i].tag)
# 此部分的輸出結(jié)果為:
# 根節(jié)點(diǎn)有2個(gè)子元素
# head標(biāo)簽有子節(jié)點(diǎn),第一個(gè)子節(jié)點(diǎn)為:title
# body標(biāo)簽有子節(jié)點(diǎn),第一個(gè)子節(jié)點(diǎn)為:p

# 2.檢查是否為elements           etree.iselement(et[i]))
for i in range(len(et)):
    print("%s是否為element : %s" % (et[i].tag, etree.iselement(et[i])))
# 此部分輸出結(jié)果為:
# head是否為element : True
# body是否為element : True

# 3.檢查是否存在父元素——getparent() 注意:是方法 不是getparent屬性!
print(et.getparent())
for i in range(len(et)):
    if et[i].getparent():
        print("%s存在父元素!" % et[i].tag)
    else:
        print("%s不存在父元素!" % et[i].tag)
# 此部分輸出結(jié)果:
# None
# head存在父元素!
# body存在父元素!

# 4.檢查同胞——getprevious()和getnext()方法
# 代碼略

# 5.尋找元素
print(et[1].find('p'))
print(et[1].find('p').tag)
# 此部分輸出結(jié)果:
# <Element p at 0x1b688db5c40>
# p

2.3 lxml的xpath方法

取出所有的a標(biāo)簽中的href鏈接:et.xpath('//a/@href')

x = et.xpath('//a/@href')
for i in range(len(x)):
    print(x[i])

輸出結(jié)果為:

http://example.com/elsie
http://example.com/lacie
http://example.com/tillie
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Python解析庫(kù) 目錄一、lxml庫(kù)二、BeautifulSoup庫(kù)三、PyQuery庫(kù) 一、lxml庫(kù) 教程:...
    Recalcitrant閱讀 1,431評(píng)論 0 0
  • 解析庫(kù)的安裝 lxml 安裝 lxml能夠支持HTML和XML 的解析支持XPath解析,安裝方式如下: lxml...
    AlanV閱讀 510評(píng)論 0 0
  • lxml解析庫(kù)用來(lái)解析html xml等安裝 https://www.cnblogs.com/magic8sky/...
    JXeddy閱讀 216評(píng)論 0 0
  • ??DOM(文檔對(duì)象模型)是針對(duì) HTML 和 XML 文檔的一個(gè) API(應(yīng)用程序編程接口)。 ??DOM 描繪...
    霜天曉閱讀 3,848評(píng)論 0 7
  • 其實(shí)今天在看之前,我在朋友圈問(wèn)了下《廉政風(fēng)云》和《流浪地球》哪個(gè)好看。 因?yàn)橥耆莾蓚€(gè)不同的風(fēng)格,一個(gè)偏懸疑,一個(gè)...
    瑪嗒嗒閱讀 334評(píng)論 1 5

友情鏈接更多精彩內(nèi)容