摘要:父節點我們可以用方法來獲取某個節點的父節點,我們用一個實例來感受一下運行結果在這里我們首先用選取了為的節點,然后調用了方法,得到其父節點,類型依然是類型。
上一篇文章:Python3網絡爬蟲實戰---29、解析庫的使用:BeautifulSoup
下一篇文章:Python3網絡爬蟲實戰---31、數據存儲:文件存儲
在上一節我們介紹了 BeautifulSoup 的使用,它是一個非常強大的網頁解析庫,可有沒有覺得它的一些方法使用有點不適應?有沒有覺得它的 CSS 選擇器功能沒有那么強大?
如果你對 Web 有所涉及,如果你比較喜歡用 CSS 選擇器,如果你對 jQuery 有所了解,那么這里有一個更適合你的解析庫—— PyQuery。
接下來我們就來感受一下 PyQuery 的強大之處。
1. 準備工作在開始之前請確保已經正確安裝好了 PyQuery,如沒有安裝可以參考第一章的安裝過程。
2. 初始化像 BeautifulSoup 一樣,PyQuery 初始化的時候也需要傳入 HTML 數據源來初始化一個操作對象,它的初始化方式有多種,比如直接傳入字符串,傳入 URL,傳文件名。下面我們來詳細介紹一下。
字符串初始化首先我們用一個實例來感受一下:
html = """""" from pyquery import PyQuery as pq doc = pq(html) print(doc("li"))
- first item
- second item
- third item
- fourth item
- fifth item
運行結果:
在這里我們首先引入了 PyQuery 這個對象,取別名為 pq,然后聲明了一個長 HTML 字符串,當作參數傳遞給 PyQuery,這樣就成功完成了初始化,然后接下來將初始化的對象傳入 CSS 選擇器,在這個實例中我們傳入 li 節點,這樣就可以選擇所有的 li 節點,打印輸出可以看到所有的 li 節點的 HTML 文本。
URL初始化初始化的參數不僅可以以字符串的形式傳遞,還可以傳入網頁的 URL,在這里只需要指定參數為 url 即可:
from pyquery import PyQuery as pq doc = pq(url="http://www.segmentfault.com") print(doc("title"))
運行結果:
SegmentFault 思否
這樣的話 PyQuery 會首先請求這個 URL,然后用得到的 HTML 內容完成初始化,其實就相當于我們用網頁的源代碼以字符串的形式傳遞給 PyQuery 來初始化。
它與下面的功能是相同的:
from pyquery import PyQuery as pq import requests doc = pq(requests.get("http://www.segmentfault.com").text) print(doc("title"))文件初始化
當然除了傳遞一個 URL,還可以傳遞本地的文件名,參數指定為 filename 即可:
from pyquery import PyQuery as pq doc = pq(filename="demo.html") print(doc("li"))
當然在這里需要有一個本地 HTML 文件 demo.html,內容是待解析的 HTML 字符串。這樣它會首先讀取本地的文件內容,然后用文件內容以字符串的形式傳遞給 PyQuery 來初始化。
以上三種初始化方式均可,當然最常用的初始化方式還是以字符串形式傳遞。
3. 基本CSS選擇器我們首先用一個實例來感受一下 PyQuery 的 CSS 選擇器的用法:
html = """""" from pyquery import PyQuery as pq doc = pq(html) print(doc("#container .list li")) print(type(doc("#container .list li")))
- first item
- second item
- third item
- fourth item
- fifth item
運行結果:
在這里我們初始化 PyQuery 對象之后,傳入了一個 CSS 選擇器,#container .list li,意思是選取 id 為 container 的節點內部的 class 為 list 的節點內部的所有 li 節點。然后打印輸出,可以看到成功獲取到了符合條件的節點。
然后我們將它的類型打印輸出,可以看到它的類型依然是 PyQuery類型。
4. 查找節點下面我們介紹一些常用的查詢函數,這些函數和 jQuery 中的函數用法也完全相同。
子節點查找子節點需要用到 find() 方法,傳入的參數是 CSS 選擇器,我們還是以上面的 HTML 為例:
from pyquery import PyQuery as pq doc = pq(html) items = doc(".list") print(type(items)) print(items) lis = items.find("li") print(type(lis)) print(lis)
運行結果:
- first item
- second item
- third item
- fourth item
- fifth item
first item second item third item fourth item fifth item
首先我們選取了 class 為 list 的節點,然后我們調用了 find() 方法,傳入了 CSS 選擇器,選取其內部的 li 節點,最后都打印輸出即可觀察到對應的查詢結果,可以發現 find() 方法會將符合條件的所有節點選擇出來,結果的類型是 PyQuery 類型。
其實 find() 的查找范圍是節點的所有子孫節點,而如果我們只想查找子節點,那可以用 children() 方法:
lis = items.children() print(type(lis)) print(lis)
運行結果:
first item second item third item fourth item fifth item
如果要篩選所有子節點中符合條件的節點,比如我們想篩選出子節點中 class 為 active 的節點,可以向 children() 方法傳入 CSS 選擇器 .active:
lis = items.children(".active") print(lis)
運行結果:
可以看到輸出的結果已經做了篩選,留下了 class 為 active 的節點。
父節點我們可以用 parent() 方法來獲取某個節點的父節點,我們用一個實例來感受一下:
html = """""" from pyquery import PyQuery as pq doc = pq(html) items = doc(".list") container = items.parent() print(type(container)) print(container)
- first item
- second item
- third item
- fourth item
- fifth item
運行結果:
- first item
- second item
- third item
- fourth item
- fifth item
在這里我們首先用 .list 選取了 class 為 list 的節點,然后調用了 parent() 方法,得到其父節點,類型依然是 PyQuery 類型。
這里的父節點是該節點的直接父節點,也就是說,它不會再去查找父節點的父節點,即祖先節點。
但是如果我們想獲取某個祖先節點怎么辦呢?可以用 parents() 方法:
from pyquery import PyQuery as pq doc = pq(html) items = doc(".list") parents = items.parents() print(type(parents)) print(parents)
運行結果:
- first item
- second item
- third item
- fourth item
- fifth item
- first item
- second item
- third item
- fourth item
- fifth item
在這里我們調用了 parents() 方法,可以看到輸出結果有兩個,一個是 class 為 wrap 的節點,一個是 id 為 container 的節點,也就是說,parents() 方法會返回所有的祖先節點。
如果我們想要篩選某個祖先節點的話可以向 parents() 方法傳入 CSS 選擇器,這樣就會返回祖先節點中符合 CSS 選擇器的節點:
parent = items.parents(".wrap") print(parent)
運行結果:
- first item
- second item
- third item
- fourth item
- fifth item
可以看到輸出結果就少了一個節點,只保留了 class 為 wrap 的節點。
兄弟節點在上面我們說明了子節點和父節點的用法,還有一種節點那就是兄弟節點,如果要獲取兄弟節點可以使用 siblings() 方法。我們還是以上面的 HTML 代碼為例來感受一下:
from pyquery import PyQuery as pq doc = pq(html) li = doc(".list .item-0.active") print(li.siblings())
在這里我們首先選擇了 class 為 list 的節點內部的 class 為 item-0 和 active 的節點,也就是第三個 li 節點。那么很明顯它的兄弟節點有四個,那就是第一、二、四、五個 li 節點。
運行結果:
可以看到運行結果也正是我們剛才所說的四個兄弟節點。
如果要篩選某個兄弟節點,我們依然可以向方法傳入 CSS 選擇器,這樣就會從所有兄弟節點中挑選出符合條件的節點了:
from pyquery import PyQuery as pq doc = pq(html) li = doc(".list .item-0.active") print(li.siblings(".active"))
在這里我們篩選了 class 為 active 的節點,通過剛才的結果我們可以觀察到 class 為 active 的兄弟節點只有第四個 li 節點,所以結果應該是一個。
運行結果:
我們剛才可以觀察到,PyQuery 的選擇結果可能是多個節點,可能是單個節點,類型都是 PyQuery 類型,并沒有返回像 BeautifulSoup 一樣的列表。
對于單個節點來說,我們可以直接打印輸出,也可直接轉成字符串:
from pyquery import PyQuery as pq doc = pq(html) li = doc(".item-0.active") print(li) print(str(li))
運行結果:
對于多個節點的結果,我們就需要遍歷來獲取了,例如這里我們把每一個 li 節點進行遍歷,,需要調用 items() 方法:
from pyquery import PyQuery as pq doc = pq(html) lis = doc("li").items() print(type(lis)) for li in lis: print(li, type(li))
運行結果:
first item second item third item fourth item fifth item
在這里我們可以發現調用 items() 方法后,會得到一個生成器,遍歷一下,就可以逐個得到 li 節點對象了,它的類型也是 PyQuery 類型,所以每個 li 節點還可以調用前面所說的方法進行選擇,比如繼續查詢子節點,尋找某個祖先節點等等,非常靈活。
6. 獲取信息提取到節點之后,我們的最終目的當然是提取節點所包含的信息了,比較重要的信息有兩類,一是獲取屬性,二是獲取文本,下面我們分別進行說明。
獲取屬性提取到某個 PyQuery 類型的節點之后,我們可以調用 attr() 方法來獲取屬性:
html = """""" from pyquery import PyQuery as pq doc = pq(html) a = doc(".item-0.active a") print(a, type(a)) print(a.attr("href"))
- first item
- second item
- third item
- fourth item
- fifth item
運行結果:
third itemlink3.html
在這里我們首先選中了 class 為 item-0 和 active 的 li 節點內的 a 節點,它的類型可以看到是 PyQuery 類型。
然后我們調用了 attr() 方法,然后傳入屬性的名稱,就可以得到這個屬性值了。
也可以通過調用 attr 屬性來獲取屬性,用法如下:
print(a.attr.href)
結果:
link3.html
結果是完全一樣的,在這里我們沒有調用方法,而是調用了 attr 屬性,然后再調用屬性名,同樣可以得到屬性值。
如果我們選中的是多個元素,然后調用 attr() 方法會出現怎樣的結果?我們用一個實例來測試一下:
a = doc("a") print(a, type(a)) print(a.attr("href")) print(a.attr.href)
運行結果:
second itemthird itemfourth itemfifth itemlink2.html link2.html
照理來說我們選中的 a 節點應該有四個,而且打印結果也是四個,但是當我們調用 attr() 方法時,返回的結果卻只是第一個。
所以當返回結果包含多個節點時,調用 attr() 方法只會得到第一個節點的屬性。
那么遇到這種情況如果我們想獲取所有的 a 節點的屬性,就需要用到上文所說的遍歷了:
from pyquery import PyQuery as pq doc = pq(html) a = doc("a") for item in a.items(): print(item.attr("href"))
運行結果:
link2.html link3.html link4.html link5.html
所以,在進行屬性獲取的時候觀察一下返回節點是一個還是多個,如果是多個,則需要遍歷才能依次獲取每個節點的屬性。
獲取文本獲取節點之后的另一個主要的操作就是獲取其內部的文本了,我們可以調用 text() 方法來獲取:
html = """""" from pyquery import PyQuery as pq doc = pq(html) a = doc(".item-0.active a") print(a) print(a.text())
- first item
- second item
- third item
- fourth item
- fifth item
運行結果:
third item third item
我們首先選中了一個 a 節點,然后調用了 text() 方法,就可以獲取其內部的文本信息了,它會忽略掉節點內部包含的所有 HTML,只返回純文字內容。
但如果我們想要獲取這個節點內部的 HTML 文本,就可以用 html() 方法:
from pyquery import PyQuery as pq doc = pq(html) li = doc(".item-0.active") print(li) print(li.html())
這里我們選中了第三個 li 節點,然后調用了 html() 方法,它返回的結果應該是li節點內的所有 HTML 文本。
運行結果:
third item
這里同樣有一個問題,如果我們選中的結果是多個節點,text() 或 html() 會返回什么內容?
我們用一個實例來看一下:
html = """ """ from pyquery import PyQuery as pq doc = pq(html) li = doc("li") print(li.html()) print(li.text()) print(type(li.text())
運行結果:
second item second item third item fourth item fifth item
結果可能比較出乎意料,我們選中的是所有的 li 節點,可以發現 html() 方法返回的是第一個 li 節點的內部 HTML 文本,而 text() 則返回了所有的 li 節點內部純文本,中間用一個空格分割開,實際上是一個字符串。
所以這個地方值得注意,如果我們得到的結果是多個節點,如果要獲取每個節點的內部 HTML 文本,則需要遍歷每個節點,而 text() 方法不需要遍歷就可以獲取,它是將所有節點取文本之后合并成一個字符串。
7. 節點操作PyQuery 提供了一系列方法來對節點進行動態修改操作,比如為某個節點添加一個 class,移除某個節點等等,這些操作有時候會為提取信息帶來極大的便利。
由于節點操作的方法太多,下面舉幾個典型的例子來說明它的用法。
addClass、removeClass我們先用一個實例來感受一下:
html = """""" from pyquery import PyQuery as pq doc = pq(html) li = doc(".item-0.active") print(li) li.removeClass("active") print(li) li.addClass("active") print(li)
- first item
- second item
- third item
- fourth item
- fifth item
首先我們選中了第三個 li 節點,然后調用了 removeClass() 方法,將 li 節點的 active 這個 class 移除,后來又調用了 addClass() 方法,又將 class 添加回來,每執行一次操作,就打印輸出一下當前 li 節點的內容。
運行結果:
可以看到一共進行了三次輸出,第二次輸出 li 節點的 active 這個 class 被移除了,第三次 class 又添加回來了。
所以說我們 addClass()、removeClass() 這些方法可以動態地改變節點的 class 屬性。
attr、text、html當然除了操作 class 這個屬性,也有 attr() 方法來專門針對屬性進行操作,也可以用 text()、html() 方法來改變節點內部的內容。
我們用實例感受一下:
html = """""" from pyquery import PyQuery as pq doc = pq(html) li = doc(".item-0.active") print(li) li.attr("name", "link") print(li) li.text("changed item") print(li) li.html("changed item") print(li)
在這里我們首先選中了 li 節點,然后調用 attr() 方法來修改屬性,第一個參數為屬性名,第二個參數為屬性值,然后我們調用了 text() 和 html() 方法來改變節點內部的內容。三次操作后分別又打印輸出當前 li 節點。
運行結果:
可以發現,調用 attr() 方法后,li 節點多了一個原本不存在的屬性 name,其值為 link,調用 text() 方法,傳入文本之后,發現 li 節點內部的文本就全被改變為傳入的字符串文本了。調用 html() 方法傳入 HTML 文本之后,li 節點內部又改變為傳入的 HTML 文本。
所以說,attr() 方法如果只傳入第一個參數屬性名,則是獲取這個屬性值,如果傳入第二個參數,可以用來修改屬性值,text() 和 html() 方法如果不傳參數是獲取節點內純文本和 HTML 文本,如果傳入參數則是進行賦值。
removeremove 顧名思義移除,remove() 方法有時會為信息的提取帶來非常大的便利。下面我們看一個實例:
html = """Hello, World""" from pyquery import PyQuery as pq doc = pq(html) wrap = doc(".wrap") print(wrap.text())This is a paragraph.
在這里有一段 HTML 文本,我們現在想提取 Hello, World 這個字符串,而不要 p 節點內部的字符串,這個怎樣來提取?
在這里我們直接先嘗試提取 class 為 wrap 的節點的內容,看看是不是我們想要的,運行結果如下:
Hello, World This is a paragraph.
然而這個結果還包含了內部的 p 節點的內容,也就是說 text() 把所有的純文本全提取出來了。如果我們想去掉 p 節點內部的文本,可以選擇再把 p 節點內的文本提取一遍,然后從整個結果中移除這個子串,但這個做法明顯比較繁瑣。
那這是 remove() 方法就可以派上用場了,我們可以接著這么做:
wrap.find("p").remove() print(wrap.text())
我們首先選中了 p 節點,然后調用了 remove() 方法將其移除,然后這時 wrap 內部就只剩下 Hello, World 這句話了,然后再利用 text()方 法提取即可。
所以說,remove() 方法可以刪除某些冗余內容,來方便我們的提取。在適當的時候使用可以極大地提高效率。
另外其實還有很多節點操作的方法,比如 append()、empty()、prepend() 等方法,他們和 jQuery 的用法是完全一致的,詳細的用法可以參考官方文檔:http://pyquery.readthedocs.io...
8. 偽類選擇器CSS 選擇器之所以強大,還有一個很重要的原因就是它支持多種多樣的偽類選擇器。例如選擇第一個節點、最后一個節點、奇偶數節點、包含某一文本的節點等等,我們用一個實例感受一下:
html = """""" from pyquery import PyQuery as pq doc = pq(html) li = doc("li:first-child") print(li) li = doc("li:last-child") print(li) li = doc("li:nth-child(2)") print(li) li = doc("li:gt(2)") print(li) li = doc("li:nth-child(2n)") print(li) li = doc("li:contains(second)") print(li)
- first item
- second item
- third item
- fourth item
- fifth item
在這里我們使用了 CSS3 的偽類選擇器,依次選擇了第一個 li 節點、最后一個 li 節點、第二個 li 節點、第三個 li 之后的 li 節點、偶數位置的 li 節點、包含 second 文本的 li 節點,功能十分強大。
更多的 CSS 選擇器的用法可以參考:http://www.w3school.com.cn/cs...
9. 結語到此為止 PyQuery 的常用用法就介紹完了,如果想查看更多的內容可以參考一下 PyQuery 的官方文檔:http://pyquery.readthedocs.io,相信有了它,解析網頁不再是難事。
上一篇文章:Python3網絡爬蟲實戰---29、解析庫的使用:BeautifulSoup
下一篇文章:Python3網絡爬蟲實戰---31、數據存儲:文件存儲
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/44082.html
摘要:運行結果如果運行結果一致則證明安裝成功。上一篇文章網絡爬蟲實戰請求庫安裝下一篇文章網絡爬蟲實戰數據庫的安裝 上一篇文章:Python3網絡爬蟲實戰---2、請求庫安裝:GeckoDriver、PhantomJS、Aiohttp下一篇文章:Python3網絡爬蟲實戰---數據庫的安裝:MySQL、MongoDB、Redis 抓取下網頁代碼之后,下一步就是從網頁中提取信息,提取信息的方式有...
摘要:的安裝是一個輕量級的關系型數據庫,以表的形式來存儲數據,本節我們來了解下它的安裝方式。相關鏈接官方網站下載地址中文教程下的安裝推薦使用安裝,執行命令即可。上一篇文章網絡爬蟲實戰解析庫的安裝下一篇文章網絡爬蟲實戰存儲庫的安裝 上一篇文章:Python3網絡爬蟲實戰---3、解析庫的安裝:LXML、BeautifulSoup、PyQuery、Tesserocr下一篇文章:Python3網絡...
摘要:如果該文件已存在,文件指針將會放在文件的結尾。運行結果以上是讀取文件的方法。為了輸出中文,我們還需要指定一個參數為,另外規定文件輸出的編碼。 上一篇文章:Python3網絡爬蟲實戰---30、解析庫的使用:PyQuery下一篇文章:Python3網絡爬蟲實戰---32、數據存儲:關系型數據庫存儲:MySQL 我們用解析器解析出數據之后,接下來的一步就是對數據進行存儲了,保存的形式可以...
摘要:上一篇文章網絡爬蟲實戰請求庫安裝下一篇文章網絡爬蟲實戰解析庫的安裝的安裝在上一節我們了解了的配置方法,配置完成之后我們便可以用來驅動瀏覽器來做相應網頁的抓取。上一篇文章網絡爬蟲實戰請求庫安裝下一篇文章網絡爬蟲實戰解析庫的安裝 上一篇文章:Python3網絡爬蟲實戰---1、請求庫安裝:Requests、Selenium、ChromeDriver下一篇文章:Python3網絡爬蟲實戰--...
摘要:解析器在解析的時候實際上是依賴于解析器的,它除了支持標準庫中的解析器,還支持一些第三方的解析器比如,下面我們對支持的解析器及它們的一些優缺點做一個簡單的對比。 上一篇文章:Python3網絡爬蟲實戰---28、解析庫的使用:XPath下一篇文章:Python3網絡爬蟲實戰---30、解析庫的使用:PyQuery 前面我們介紹了正則表達式的相關用法,但是一旦正則寫的有問題,可能得到的就...
閱讀 1769·2021-09-28 09:43
閱讀 1120·2021-09-23 11:22
閱讀 2730·2021-09-14 18:05
閱讀 1829·2019-08-30 15:52
閱讀 2818·2019-08-30 10:55
閱讀 2017·2019-08-29 16:58
閱讀 1329·2019-08-29 16:37
閱讀 3042·2019-08-29 16:25