Python解析庫

Python解析庫

目錄
一、lxml庫
二、BeautifulSoup庫
三、PyQuery庫

一、lxml庫

教程:https://www.w3school.com.cn/xpath/index.asp

1.安裝lxml庫

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ lxml

2.解析規(guī)則

解析規(guī)則:XPath

表達式 描述
nodename 選取此節(jié)點的所有子節(jié)點
/ 從當前節(jié)點選取直接子節(jié)點
// 從當前節(jié)點選取所有子孫節(jié)點
. 選取當前節(jié)點
.. 選取當前節(jié)點的父節(jié)點
@ 選取屬性
* 通配符,選擇所有元素節(jié)點與元素名
@* 選取所有屬性
[@attrib] 選取具有給定屬性的所有元素
[@attrib='value'] 選取給定屬性具有給定值的所有元素
[tag] 選取所有具有指定元素的直接子節(jié)點
[tag='text'] 選取所有具有指定元素并且文本內容是text節(jié)點

3.XPath運算符

運算符 描述 實例 返回值
or age=19 or age=20 如果age等于19或者等于20則返回true反正返回false
and age>19 and age<21 如果age等于20則返回true,否則返回false
mod 取余 5 mod 2 1
| 取兩個節(jié)點的集合 //book | //cd 返回所有擁有book和cd元素的節(jié)點集合
+ 6+4 10
- 6-4 2
* 6*4 24
div 除法 8 div 4 2
= 等于 age=19 True或False
!= 不等于 age!=19 True或False
< 小于 age<19 True或False
<= 小于或等于 age<=19 True或False
> 大于 age>19 True或False
>= 大于或等于 age>=19 True或False

4.構建etree實例

(1)從文本構建

示例:

from lxml import etree
def load_text():
    text = """
    <div>
        <ul>
            <li class="item-0"><a href="link1.html">first item</a></li>
            <li class="item-1"><a href="link2.html">second item</a></li>
            <li class="item-inactive"><a href="link3.html">third item</a></li>
            <li class="item-1"><a href="link4.html">forth item</a></li>
            <li class="item-0"><a href="link5.html">fifth item</a>
        </ul>
    </div>
    """

    html = etree.HTML(text)
    result = etree.tostring(html)
    print(result.decode("utf-8"))
運行結果

經過處理后的html代碼會被自動修復,如添加一些缺失的標簽。

(2)從文件構建

示例:

from lxml import etree
def load_text():
    html = etree.parse("./test.html", etree.HTMLParser())
    print(type(html))
    result = etree.tostring(html)
    print(result.decode("utf-8"))

注意:etree.tostring()方法返回的數據為bytes類型,需要調用decode方法將其轉換成sgr類型。

5.節(jié)點選取

(1)選中所有節(jié)點

  • 選中所有節(jié)點

//*

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://*")
print(result)
  • 選中所有的某一類節(jié)點

//標簽

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://li")
print(result)

(2)選取子孫節(jié)點

①選取直接子節(jié)點

/標簽
/child::標簽

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://li/a")
print(result)

②選取后代節(jié)點

//標簽
/descendant::標簽

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://li//a")
print(result)

(3)選取祖先節(jié)點

①選取父節(jié)點

  • 方法1

/..

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://a/..")
print(result)
  • 方法2

/parent::

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://a/parent::*")
print(result)

②選取祖先節(jié)點

/ancestor::*
/ancestor::標簽

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://li[1]/ancestor::*")
print(result)

(4)選取兄弟節(jié)點

# 獲取該節(jié)點后的所有兄弟節(jié)點以及這些兄弟節(jié)點的所有子孫節(jié)點
result = html.xpath("http://li[1]/following::*")
print(result)

# 獲取該節(jié)點后的所有兄弟節(jié)點以及這些兄弟節(jié)點的所有子孫節(jié)點中的第一個節(jié)點
result = html.xpath("http://li[1]/following::*[1]")
print(result)

# 獲取該節(jié)點后的所有兄弟節(jié)點
result = html.xpath("http://li[1]/following-sibling::*")
print(result)

(5)屬性匹配

  • 選取具有某屬性的節(jié)點

[@屬性]

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://li[@class]")
print(result)

選取擁有class屬性的li標簽。

  • 選取具有某屬性且其值符合要求的節(jié)點

[@屬性=值]

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://li[@class='item-0']")
print(result)

選取擁有屬性class='item-0'的li標簽。

(6)屬性多值匹配

[contains(@屬性, 值)]

text = """
<li class="li li-first"><a href="link1.html">first item</a></li>
"""
html = etree.HTML(text)
result = html.xpath("http://li[@class='li']/a/text()")
print(result)

result = html.xpath("http://li[contains(@class, 'li')]/a/text()")
print(result)
運行結果

(7)多屬性匹配

[contains(@屬性, 值) and @屬性=值]
[contains(@屬性, 值) or @屬性=值]

text = """
<li class="li li-first" name='item'><a href="link1.html">first item</a></li>
"""
html = etree.HTML(text)
result = html.xpath("http://li[contains(@class, 'li') and @name='item']/a/text()")
print(result)

(8)按順序位置選取節(jié)點

# 選取第一個節(jié)點
html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://li[1]/a/text()")
print(result)

# 選取最后一個節(jié)點
result = html.xpath("http://li[last()]/a/text()")
print(result)

# 選取前兩個節(jié)點
result = html.xpath("http://li[position() < 3]/a/text()")
print(result)

# 選取倒數第三個節(jié)點
result = html.xpath("http://li[last() - 2]/a/text()")
print(result)
運行結果

6.屬性獲取

(1)獲取節(jié)點屬性

/@*
/@屬性

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://a[@href='link4.html']/../@class")
print(result)

獲取擁有屬性href='link4.html的a標簽的父親節(jié)點的class屬性的值。

(2)獲取節(jié)點內容

/text()

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("http://li[@class='item-0']/text()")
print(result)

獲取擁有屬性class='item-0'的li標簽的文本內容。

二、BeautifulSoup庫

文檔:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/

1.安裝BeautifulSoup庫

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ beautifulsoup4
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ bs4

2.解析

(1)文檔解析語法

soup = BeautifulSoup(待解析文檔, 解析器)

(2)解析器

  • 常用解析器
解析器 使用方法 性能
Python標準庫 BeautifulSoup(html_doc,"html.parser") 執(zhí)行速度適中
文檔容錯能力強
lxml HTML 解析器 BeautifulSoup(html_doc,"lxml") 執(zhí)行速度快
容錯能力強
要求安裝lxml擴展
lxml XML 解析器 BeautifulSoup(html_doc,"xml")
BeautifulSoup(markup,["lxml", "xml"])
支持解析xml
執(zhí)行速度快
要求安裝外部擴展
html5lib解析器 BeautifulSoup(html_doc,"html5lib") 以瀏覽器的方式解析文檔,生成HTML5格式文檔
執(zhí)行速度慢
最好的容錯性
要求安裝html5lib擴展
  • 解析器安裝
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ lxml
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ html5lib

3.修復文檔

soup = BeautifulSoup(html, "lxml")
print(soup.prettify())

4.節(jié)點選取

# 整個HTML文檔
soup
# title節(jié)點的HTML文本
soup.title
# title節(jié)點的文本內容
soup.title.string
print(type(soup))
print(type(soup.title))
print(type(soup.title.string))
運行結果

(1)按標簽名

# 獲取節(jié)點名稱
print(soup.title.name)

# 獲取屬性值(字典類型)
print(soup.p.attrs)
print(soup.p.attrs['name'])

# 獲取文本內容(str類型)
print(soup.p.string)

# 嵌套選擇
print(soup.head.title)

# 關聯選擇
# contents屬性:選取直接子節(jié)點
print(soup.p.contents)

(2)按節(jié)點關系

# 獲取直接子節(jié)點(返回列表)
print(soup.p.contents)

# 獲取直接子節(jié)點(返回生成器)
for i, child in enumerate(soup.p.children):
    print(i, child)
    
# 獲取所有子孫節(jié)點(返回生成器)
for i, child in enumerate(soup.p.descendants):
    print(i, child)

獲取直接父節(jié)點:parent
獲取祖先節(jié)點:parents
獲取兄弟節(jié)點:

next_sibling(下一個兄弟節(jié)點) | previous_sibling(上一個兄弟節(jié)點)
next_siblings(后面的所有兄弟節(jié)點) | previous_siblings(前面的所有兄弟及誒單)

(3)find方法

  • find_all()方法:返回符合條件的所有節(jié)點元素
# 通過name查找
print(soup.find_all(name="ul"))
print(type(soup.find_all(name="ul")[0]))
print(soup.find_all(name="ul")[0].find_all(name='li'))

# 通過屬性查找
print(soup.find_all(attrs={'id': 'list'}))
print(soup.find_all(attrs={'id': 'list', 'name': 'elements'}))
print(soup.find_all(id='list2'))
print(soup.find_all(class_='list'))

# 通過文本查找節(jié)點
import re
print(soup.find_all(text=re.compile('^1+')))
print(type(soup.find_all(text=re.compile('^1+'))[0]))
  • find():返回單個元素(即匹配的第一個元素)

find_parent() | find_parents()
find_next_sibling() | find_next_siblings()
find_previous_sibling() | find_previous_siblings()
find_next() | find_all_next():返回節(jié)點后 第一個|所有 符合條件的節(jié)點
find_previous() | find_all_previous():返回節(jié)點前 第一個|所有 符合條件的節(jié)點

(4)CSS選擇器

soup.select("CSS選擇器")

三、PyQuery庫

1.安裝PyQuery庫

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pyquery

2.語法類似jQuery

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容