第67天:PyQuery 詳解

by 閒歡

PyQuery 庫是一個非常強大又靈活的網頁解析庫,如果你有前端開發經驗,那麼你應該接觸過 jQuery ,那麼 PyQuery 就是你非常絕佳的選擇,PyQuery 是 Python 仿照 jQuery 的嚴格實現,語法與 jQuery 幾乎完全相同。

安裝

跟安裝其他庫一樣:

>>> pip3 install pyquery

安裝了之後,在程序裏面就可以引用了,引用方法跟其他庫類似:

from pyquery import PyQuery as pq

初始化

PyQuery 可以將 HTML 字符串初始化爲對象,也可以將 HTML 文件初始化爲對象,甚至可以將請求的響應初始化爲對象。下面我們一個個來介紹。

初始化字符串

對於一個標準的 HTML 字符串,PyQuery 可以直接初始化爲對象:

html = """
<html>
    <head>
        我愛我的祖國
        <title>China</title>
    </head>
    <body>
        <ul id="container">
            <li class="li1">五星</li>
            <li class="li2">紅旗</li>
            <li class="li3">迎風飄揚</li>
        </ul>
    </body>
</html>
"""

doc = pq(html)
print(type(doc))
print(doc)

# 輸出結果
<class 'pyquery.pyquery.PyQuery'>
<html>
    <head>
        我愛我的祖國
        <title>China</title>
    </head>
    <body>
        <ul id="container">
            <li class="li1">五星</li>
            <li class="li2">紅旗</li>
            <li class="li3">迎風飄揚</li>
        </ul>
    </body>
</html>

我們可以看到,HTML 字符串初始化後,打印出來的是一個 PyQuery 對象。

如果我們的字符串不是 HTML 格式內容,PyQuery 會自動加上段落標籤將字符串內容包裝成 HTML 內容。例如:

test = '''
this is a string
this is second row
'''

doc = pq(test)
print(type(doc))
print(doc)

# 輸出結果
<class 'pyquery.pyquery.PyQuery'>
<p>this is a string
this is second row
</p>

初始化 HTML 文件

初始化文件,只需要加個 filename 參數,指明 文件路徑即可:

#filename參數爲html文件路徑
test_html = pq(filename='test.html')
print(type(test_html))
print(test_html)

# 輸出結果
<class 'pyquery.pyquery.PyQuery'>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
</head>
<body>

</body>
</html>

如果文件不是 HTML 文件,那麼初始化的時候會自動加上 HTML 標籤。例如:

#filename參數爲html文件路徑
test_txt = pq(filename='test.txt')
print(type(test_txt))
print(test_txt)

# 輸出結果
<class 'pyquery.pyquery.PyQuery'>
<html><body><p>this is a txt</p></body></html>

我的 test.txt 文件中只有一行內容: this is a txt。初始化完後,自動添加了 HTML 標籤。

初始化請求響應

我們可以把請求的網址內容初始化爲 PyQuery 對象,只需要加個參數 url ,將網址賦值給它即可。例如:

response = pq(url='https://www.baidu.com')
print(type(response))
print(response)

# 輸出結果
<class 'pyquery.pyquery.PyQuery'>
<html> <head><meta http-equiv="content-type" content="text/html;charset=utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=Edge"/><meta content="always" name="referrer"/><link
...

我們請求百度的首頁,然後初始化爲對象,後面內容較多,因此省略。

常用 CSS 選擇器

PyQuery 裏面 CSS 選擇器的用法跟 jQuery 裏面是一樣的,例如,針對上面的 HTML 字符串內容,我們獲取 id 爲 container 的標籤,然後打印出來:

doc = pq(html)
print(type(doc('#container')))
print(doc('#container'))

# 輸出結果
<class 'pyquery.pyquery.PyQuery'>
<ul id="container">
            <li class="li1">五星</li>
            <li class="li2">紅旗</li>
            <li class="li3">迎風飄揚</li>
        </ul>

我們也可以用 class 選擇器,例如:

print(type(doc('.li2')))
print(doc('.li2'))

# 輸出結果
<class 'pyquery.pyquery.PyQuery'>
<li class="li2">紅旗</li>

再複雜一點,我們可以使用多層選擇器,例如:

print(doc('html #container'))

# 輸出結果
<ul id="container">
            <li class="li1">五星</li>
            <li class="li2">紅旗</li>
            <li class="li3">迎風飄揚</li>
        </ul>

當然,我們同樣可以根據 CSS 選擇器修改 HTML 標籤的內容:

li2 = doc('.li2')
li2.css('font-size', '18px')
print(li2)

# 輸出結果
<li class="li2" style="font-size: 18px">紅旗</li>

這裏我們給 class 爲“li2”的標籤加了字體的大小,可以看到返回的內容中有了 style 屬性。

雖然 PyQuery 有修改 HTML 內容的方法,但是我們一般不會用到,因爲我們一般是解析 HTML 內容,而不是去修改它,大家瞭解一下即可。

僞類選擇器

僞類(Pseudo-classes)是指在 HTML 中,同一個標籤,根據其不同的狀態,有不同的顯示樣式。詳細的用法可以參考: https://www.runoob.com/css/css-pseudo-classes.html ,裏面有詳細的介紹。

我們主要應用僞類選擇器來解析 HTML,獲取我們所需的數據。例如:

pseudo_doc = pq(html)
print(pseudo_doc('li:nth-child(2)'))
#打印第一個li標籤
print(pseudo_doc('li:first-child'))
#打印最後一個標籤
print(pseudo_doc('li:last-child'))

# 輸出結果
<li class="li2">紅旗</li>
            
<li class="li1">五星</li>
            
<li class="li3">迎風飄揚</li>

我們也可以用 contains 方法來篩選內容,例如:

html = """
<html>
    <head>
        我愛我的祖國
        <title>China</title>
    </head>
    <body>
        <ul id="container">
            <li class="li1">五星啊</li>
            <li class="li2">紅旗</li>
            <li class="li3">迎風飄揚啊</li>
        </ul>
    </body>
</html>
"""

pseudo_doc = pq(html)

#找到含有Python的li標籤
print(pseudo_doc("li:contains('五星')"))

#找到含有好的li標籤
print(pseudo_doc("li:contains('紅')"))

#找到含有啊的li標籤
print(pseudo_doc("li:contains('啊')"))

# 輸出結果
<li class="li1">五星啊</li>
            
<li class="li2">紅旗</li>

<li class="li1">五星啊</li>
            <li class="li3">迎風飄揚啊</li>

我們可以看到,如果查找的結果有多條記錄,那麼結果會將多條記錄拼在一起。當然,如果查找的內容不存在,就會返回空。

查找標籤

我們可以按照條件在 Pyquery 對象中查找符合條件的標籤,類似於 BeautifulSoup 中的 find 方法。
例如,我要查找 id 爲 container 的標籤:

#打印id爲container的標籤
print(doc.find('#container'))

# 輸出結果
<ul id="container">
            <li class="li1">五星啊</li>
            <li class="li2">紅旗</li>
            <li class="li3">迎風飄揚啊</li>
        </ul>

我要查找 id 爲 container 的標籤的子標籤,使用 children 方法就可以實現:

#打印id爲container的標籤的子標籤
container = doc.find('#container')
print(container.children())

# 輸出結果
<li class="li1">五星啊</li>
            <li class="li2">紅旗</li>
            <li class="li3">迎風飄揚啊</li>

查找父標籤,我們可以用 parent 方法:

#打印id爲container的標籤的父標籤
container = doc.find('#container')
print(container.parent())

# 輸出結果
<body>
        <ul id="container">
            <li class="li1">五星啊</li>
            <li class="li2">紅旗</li>
            <li class="li3">迎風飄揚啊</li>
        </ul>
    </body>

查找兄弟標籤,我們用 siblings 方法:

#打印class爲li2的標籤的兄弟標籤
li2 = doc.find('.li2')
print(li2.siblings())

# 輸出結果
<li class="li1">五星啊</li>
            <li class="li3">迎風飄揚啊</li>

標籤信息的提取

前面我們講的都是怎麼定位到標籤,這只是我們解析數據的第一步,接下來我們需要從標籤中提取我們需要的信息。

如果你需要提取標籤的屬性值,可以用 .attr() 方法,例如:

#獲取li2的class屬性值
print(doc('.li2').attr('class'))

# 輸出結果
li2

如果你細腰提取標籤內的文本,我們可以用 .text() 方法,例如:

#獲取li2的文本
print(doc('.li2').text())

# 輸出結果
紅旗

如果要獲取某個標籤下面的所有文本(包含子標籤的),怎麼做?我們來看下個例子:

#獲取html標籤下面的所有文本
print(doc('html').text())

# 輸出結果
我愛我的祖國
China
五星啊
紅旗
迎風飄揚啊

很簡單,我們只需要找到這個標籤,使用 .text() 方法。

如果我們要獲取某個標籤下面的所有文本,但是要排除某些標籤的文本,該怎麼做?我們來看下個例子:

#排除部分標籤文本
tag = doc('html')
tag.remove('title')
print(tag.text())

# 輸出結果
我愛我的祖國
五星啊
紅旗
迎風飄揚啊

我們可以用 .remove() 來刪除某些標籤,上面例子中可以看到,我們把 title 標籤去掉了,title 標籤對應的內容 China 也就去掉了。

PyQuery 處理複雜的網址請求

前面我們介紹了 PyQuery 可以獲取網址請求的 HTML 內容,並轉化爲對象。我們在請求 URL 時,或許會遇到需要附帶一些參數的情況,這些自定義的參數在 PyQuery 請求時也是支持的,例如 cookies 和 headers,我們看例子:

cookies = {'Cookie':'cookie'}
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}

response = pq(url='https://www.baidu.com',headers=headers,cookies=cookies)
print(response)

#返回(省略)

<head>
    
    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
...

總結

這篇文章給大家介紹了 PyQuery 的常見使用方法,大家如果用的熟練的話,還是可以極大地節約我們解析 HTML 網頁內容的時間的。PyQuery 可以稱得上是爬蟲神器,還有一些用法由於篇幅有限,沒有進行介紹。大家可以去官網詳細查看,官網地址: https://pythonhosted.org/pyquery/

文中示例代碼:Python-100-days-day067

關注公衆號:python技術,回覆"python"一起學習交流

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章