PyQuery 庫是一個(gè)非常強(qiáng)大又靈活的網(wǎng)頁解析庫,如果你有前端開發(fā)經(jīng)驗(yàn),那么你應(yīng)該接觸過 jQuery ,那么PyQuery就是你非常絕佳的選擇,PyQuery 是 Python 仿照 jQuery 的嚴(yán)格實(shí)現(xiàn),語法與 jQuery 幾乎完全相同。
安裝
跟安裝其他庫一樣:
>>> pip3 install pyquery
安裝了之后,在程序里面就可以引用了,引用方法跟其他庫類似:
from pyquery import PyQuery as pq
初始化
PyQuery 可以將 HTML 字符串初始化為對(duì)象,也可以將 HTML 文件初始化為對(duì)象,甚至可以將請(qǐng)求的響應(yīng)初始化為對(duì)象。下面我們一個(gè)個(gè)來介紹。
初始化字符串
對(duì)于一個(gè)標(biāo)準(zhǔn)的 HTML 字符串,PyQuery 可以直接初始化為對(duì)象:
html = """
<html>
<head>
我愛我的祖國
<title>China</title>
</head>
<body>
<ul id="container">
<li class="li1">五星</li>
<li class="li2">紅旗</li>
<li class="li3">迎風(fēng)飄揚(yáng)</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">迎風(fēng)飄揚(yáng)</li>
</ul>
</body>
</html>
我們可以看到,HTML 字符串初始化后,打印出來的是一個(gè) PyQuery 對(duì)象。
如果我們的字符串不是 HTML 格式內(nèi)容,PyQuery 會(huì)自動(dòng)加上段落標(biāo)簽將字符串內(nèi)容包裝成 HTML 內(nèi)容。例如:
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 文件
初始化文件,只需要加個(gè) filename 參數(shù),指明 文件路徑即可:
#filename參數(shù)為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 文件,那么初始化的時(shí)候會(huì)自動(dòng)加上 HTML 標(biāo)簽。例如:
#filename參數(shù)為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 文件中只有一行內(nèi)容: this is a txt。初始化完后,自動(dòng)添加了 HTML 標(biāo)簽。
初始化請(qǐng)求響應(yīng)
我們可以把請(qǐng)求的網(wǎng)址內(nèi)容初始化為 PyQuery 對(duì)象,只需要加個(gè)參數(shù) url ,將網(wǎng)址賦值給它即可。例如:
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
...
我們請(qǐng)求百度的首頁,然后初始化為對(duì)象,后面內(nèi)容較多,因此省略。
常用 CSS 選擇器
PyQuery 里面 CSS 選擇器的用法跟 jQuery 里面是一樣的,例如,針對(duì)上面的 HTML 字符串內(nèi)容,我們獲取 id 為 container 的標(biāo)簽,然后打印出來:
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">迎風(fēng)飄揚(yáng)</li>
</ul>
我們也可以用 class 選擇器,例如:
print(type(doc('.li2')))
print(doc('.li2'))
#返回
<class 'pyquery.pyquery.PyQuery'>
<li class="li2">紅旗</li>
再復(fù)雜一點(diǎn),我們可以使用多層選擇器,例如:
print(doc('html #container'))
#返回
<ul id="container">
<li class="li1">五星</li>
<li class="li2">紅旗</li>
<li class="li3">迎風(fēng)飄揚(yáng)</li>
</ul>
當(dāng)然,我們同樣可以根據(jù) CSS 選擇器修改 HTML 標(biāo)簽的內(nèi)容:
li2 = doc('.li2')
li2.css('font-size', '18px')
print(li2)
#返回
<li class="li2" style="font-size: 18px">紅旗</li>
這里我們給 class 為“l(fā)i2”的標(biāo)簽加了字體的大小,可以看到返回的內(nèi)容中有了 style 屬性。
雖然 PyQuery 有修改 HTML 內(nèi)容的方法,但是我們一般不會(huì)用到,因?yàn)槲覀円话闶墙馕?HTML 內(nèi)容,而不是去修改它,大家了解一下即可。
偽類選擇器
偽類(Pseudo-classes)是指在 HTML 中,同一個(gè)標(biāo)簽,根據(jù)其不同的狀態(tài),有不同的顯示樣式。詳細(xì)的用法可以參考: https://www.runoob.com/css/css-pseudo-classes.html ,里面有詳細(xì)的介紹。
我們主要應(yīng)用偽類選擇器來解析 HTML,獲取我們所需的數(shù)據(jù)。例如:
pseudo_doc = pq(html)
print(pseudo_doc('li:nth-child(2)'))
#打印第一個(gè)li標(biāo)簽
print(pseudo_doc('li:first-child'))
#打印最后一個(gè)標(biāo)簽
print(pseudo_doc('li:last-child'))
#返回
<li class="li2">紅旗</li>
<li class="li1">五星</li>
<li class="li3">迎風(fēng)飄揚(yáng)</li>
我們也可以用 contains 方法來篩選內(nèi)容,例如:
html = """
<html>
<head>
我愛我的祖國
<title>China</title>
</head>
<body>
<ul id="container">
<li class="li1">五星啊</li>
<li class="li2">紅旗</li>
<li class="li3">迎風(fēng)飄揚(yáng)啊</li>
</ul>
</body>
</html>
"""
pseudo_doc = pq(html)
#找到含有Python的li標(biāo)簽
print(pseudo_doc("li:contains('五星')"))
#找到含有好的li標(biāo)簽
print(pseudo_doc("li:contains('紅')"))
#找到含有啊的li標(biāo)簽
print(pseudo_doc("li:contains('啊')"))
#返回
<li class="li1">五星啊</li>
<li class="li2">紅旗</li>
<li class="li1">五星啊</li>
<li class="li3">迎風(fēng)飄揚(yáng)啊</li>
我們可以看到,如果查找的結(jié)果有多條記錄,那么結(jié)果會(huì)將多條記錄拼在一起。當(dāng)然,如果查找的內(nèi)容不存在,就會(huì)返回空。
查找標(biāo)簽
我們可以按照條件在 Pyquery 對(duì)象中查找符合條件的標(biāo)簽,類似于 BeautifulSoup 中的 find 方法。
例如,我要查找 id 為 container 的標(biāo)簽:
#打印id為container的標(biāo)簽
print(doc.find('#container'))
#返回
<ul id="container">
<li class="li1">五星啊</li>
<li class="li2">紅旗</li>
<li class="li3">迎風(fēng)飄揚(yáng)啊</li>
</ul>
我要查找 id 為 container 的標(biāo)簽的子標(biāo)簽,使用 children 方法就可以實(shí)現(xiàn):
#打印id為container的標(biāo)簽的子標(biāo)簽
container = doc.find('#container')
print(container.children())
#返回
<li class="li1">五星啊</li>
<li class="li2">紅旗</li>
<li class="li3">迎風(fēng)飄揚(yáng)啊</li>
查找父標(biāo)簽,我們可以用 parent 方法:
#打印id為container的標(biāo)簽的父標(biāo)簽
container = doc.find('#container')
print(container.parent())
#返回
<body>
<ul id="container">
<li class="li1">五星啊</li>
<li class="li2">紅旗</li>
<li class="li3">迎風(fēng)飄揚(yáng)啊</li>
</ul>
</body>
查找兄弟標(biāo)簽,我們用 siblings 方法:
#打印class為li2的標(biāo)簽的兄弟標(biāo)簽
li2 = doc.find('.li2')
print(li2.siblings())
#返回
<li class="li1">五星啊</li>
<li class="li3">迎風(fēng)飄揚(yáng)啊</li>
標(biāo)簽信息的提取
前面我們講的都是怎么定位到標(biāo)簽,這只是我們解析數(shù)據(jù)的第一步,接下來我們需要從標(biāo)簽中提取我們需要的信息。
如果你需要提取標(biāo)簽的屬性值,可以用 .attr() 方法,例如:
#獲取li2的class屬性值
print(doc('.li2').attr('class'))
#返回
li2
如果你細(xì)腰提取標(biāo)簽內(nèi)的文本,我們可以用 .text() 方法,例如:
#獲取li2的文本
print(doc('.li2').text())
#返回
紅旗
如果要獲取某個(gè)標(biāo)簽下面的所有文本(包含子標(biāo)簽的),怎么做?我們來看下個(gè)例子:
#獲取html標(biāo)簽下面的所有文本
print(doc('html').text())
#返回
我愛我的祖國
China
五星啊
紅旗
迎風(fēng)飄揚(yáng)啊
很簡單,我們只需要找到這個(gè)標(biāo)簽,使用 .text() 方法。
如果我們要獲取某個(gè)標(biāo)簽下面的所有文本,但是要排除某些標(biāo)簽的文本,該怎么做?我們來看下個(gè)例子:
#排除部分標(biāo)簽文本
tag = doc('html')
tag.remove('title')
print(tag.text())
#返回
我愛我的祖國
五星啊
紅旗
迎風(fēng)飄揚(yáng)啊
我們可以用 .remove() 來刪除某些標(biāo)簽,上面例子中可以看到,我們把 title 標(biāo)簽去掉了,title 標(biāo)簽對(duì)應(yīng)的內(nèi)容 China 也就去掉了。
PyQuery 處理復(fù)雜的網(wǎng)址請(qǐng)求
前面我們介紹了 PyQuery 可以獲取網(wǎng)址請(qǐng)求的 HTML 內(nèi)容,并轉(zhuǎn)化為對(duì)象。我們在請(qǐng)求 URL 時(shí),或許會(huì)遇到需要附帶一些參數(shù)的情況,這些自定義的參數(shù)在 PyQuery 請(qǐng)求時(shí)也是支持的,例如 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"/>
...
總結(jié)
這篇文章給大家介紹了 PyQuery 的常見使用方法,大家如果用的熟練的話,還是可以極大地節(jié)約我們解析 HTML 網(wǎng)頁內(nèi)容的時(shí)間的。PyQuery 可以稱得上是爬蟲神器,還有一些用法由于篇幅有限,沒有進(jìn)行介紹。大家可以去官網(wǎng)詳細(xì)查看,官網(wǎng)地址: https://pythonhosted.org/pyquery/ 。