日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

Pyquery:一個靈活方便的 HTML 解析庫

來源: 責編: 時間:2023-12-01 17:14:47 238觀看
導讀楔子在工作中難免會遇到解析 HTML 的場景,比如將網頁下載下來之后,要解析出里面圖片的路徑、指定標簽里的文本等等。而 pyquery 專門負責做這件事,它是仿照 jquery 設計的,用起來非常方便。并且 pyquery 底層基于 lxml,而

楔子

D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

在工作中難免會遇到解析 HTML 的場景,比如將網頁下載下來之后,要解析出里面圖片的路徑、指定標簽里的文本等等。D4i28資訊網——每日最新資訊28at.com

而 pyquery 專門負責做這件事,它是仿照 jquery 設計的,用起來非常方便。并且 pyquery 底層基于 lxml,而 lxml 是使用 Cython 實現的,所以 pyquery 的速度也有保證。D4i28資訊網——每日最新資訊28at.com

from pyquery import PyQueryhtml = """<body>    <p>        古明地覺的編程教室    </p></body>"""p = PyQuery(html)print(type(p))"""<class 'pyquery.pyquery.PyQuery'>"""# 打印 PyQuery 對象會直接顯示 HTML 內容print(p)"""<body>    <p>        古明地覺的編程教室    </p></body>"""

我們在獲取 HTML 之后,直接傳遞 PyQuery 中,然后通過屬性選擇器即可獲取指定的內容。D4i28資訊網——每日最新資訊28at.com

另外除了傳遞 HTML 文本之外,還可以傳遞一個 URL,或者 HTML 文件。D4i28資訊網——每日最新資訊28at.com

from pyquery import PyQuery# 傳遞一個 url, 會自動調用 urlopen 下載內容p1 = PyQuery(url="https://www.baidu.com", encoding="utf-8")# 傳遞一個 html 文件, 會自動打開并讀取p2 = PyQuery(filename="1.html")

后兩種方式其實不是很常用,我們一般還是會搭配 requests 或者 httpx,下載完頁面之后直接丟給 PyQuery。D4i28資訊網——每日最新資訊28at.com

接下來我們看看如何篩選指定的標簽,多說一句,我個人非常喜歡這個庫,在解析 HTML 的時候首先想到的就是它。D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

CSS 選擇器

D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

pyquery 是模仿 jquery 設計的,顯然它也是通過類似于 CSS 選擇器的方式進行篩選,下面介紹一些常用的選擇器。D4i28資訊網——每日最新資訊28at.com

from pyquery import PyQueryhtml = """<body>    <div class="div_cls1 div_cls2">        <p>S 老師不想你們為了她兩敗俱傷</p>        <p class="p_cls1">高老師總能分享出好東西</p>        <div class="div_cls3">            <p id="six_six_six">                我也退了,都怪我說了不該說的            </p>        </div>    </div>    <div>        <a ></a>        <p>            <a ></a>        </p>    </div>    <div class="div_cls1">        <span>嘿嘿嘿</span>    </div></body>"""p = PyQuery(html)

我們以上面這個 HTML 為例,來看看相關操作。D4i28資訊網——每日最新資訊28at.com

基于標簽進行選擇

# 選擇所有的 p 標簽print(p("p"))"""<p>S 老師不想你們為了她兩敗俱傷</p>        <p class="p_cls1">高老師總能分享出好東西</p>        <p id="six_six_six">                我也退了,都怪我說了不該說的            </p>        <p>            <a />        </p>    """

會選擇所有指定的標簽,并且包含標簽里面的內容。D4i28資訊網——每日最新資訊28at.com

同時選擇多個標簽

在基于標簽選擇時,也可以同時選擇多個標簽。D4i28資訊網——每日最新資訊28at.com

# 選擇所有的 p 標簽和 a 標簽print(p("p,a"))"""<p>S 老師不想你們為了她兩敗俱傷</p>        <p class="p_cls1">高老師總能分享出好東西</p>        <p id="six_six_six">                我也退了,都怪我說了不該說的            </p>        <a />        <p>            <a />        </p>    <a ""

多個標簽之間使用逗號分隔,會將多個標簽都篩選出來。D4i28資訊網——每日最新資訊28at.com

注意:篩選的標簽之間是獨立的,比如第二個 a 標簽,它在 p 標簽里面。我們篩選 p 標簽的時候,已經將它內部的 a 標簽篩選出來了,但在篩選 a 標簽的時候又篩選出來一次,因此標簽之間是獨立的。D4i28資訊網——每日最新資訊28at.com

選擇指定標簽下的子標簽

# 選擇所有的 div 標簽下的所有 a 標簽print(p("div a"))"""<a />        <a ""

多個標簽使用空格分隔,表示篩選層級,比如 tag1 tag2 tag3,表示篩選所有 tag1 標簽下的所有 tag2 標簽下的所有 tag3 標簽。D4i28資訊網——每日最新資訊28at.com

div a 表示從所有 div 的子孫節點中選擇 a 標簽,如果只希望從兒子節點中選擇呢?D4i28資訊網——每日最新資訊28at.com

# 選擇所有的 div 標簽下的所有 a 標簽,但只從兒子節點中選擇# 第二個 a 標簽的外部套了個 p 標簽,所以不符合篩選條件print(p("div>a"))"""<a ""

當標簽之間是空格,那么會從子孫節點當中選擇;當標簽之間是大于號,那么只會從兒子節點當中選擇。D4i28資訊網——每日最新資訊28at.com

按照 id 選擇標簽

# 選擇 id = "six_six_six" 的標簽print(p("#six_six_six"))"""<p id="six_six_six">                我也退了,都怪我說了不該說的            </p>"""

id 在一個 html 中具有唯一性,所以有 id 屬性的話,那么會非常好定位。D4i28資訊網——每日最新資訊28at.com

按照 class 選擇標簽

p = PyQuery(html)# 選擇 class 等于 "p_cls1" 的標簽print(p(".p_cls1"))"""<p class="p_cls1">高老師總能分享出好東西</p>"""

選擇所有 class 屬性等于 p_cls1 的標簽,但是注意,一個標簽可以同時擁有多個 class。D4i28資訊網——每日最新資訊28at.com

print(p(".div_cls1"))"""<div class="div_cls1 div_cls2">        <p>S 老師不想你們為了她兩敗俱傷</p>        <p class="p_cls1">高老師總能分享出好東西</p>        <div class="div_cls3">            <p id="six_six_six">                我也退了,都怪我說了不該說的            </p>        </div>    </div>    <div class="div_cls1">        <span>嘿嘿嘿</span>    </div>        """

我們看到兩個 div 都應用了 div_cls1 這個 class,因此它們都被篩選了出來。而第一個 div 除了 div_cls1,還應用了 div_cls2 這個 class。D4i28資訊網——每日最新資訊28at.com

那么問題來了,如果我們希望選擇同時應用了 div_cls1 和 div_cls2 的標簽該怎么做呢?D4i28資訊網——每日最新資訊28at.com

print(p(".div_cls1.div_cls2"))"""<div class="div_cls1 div_cls2">        <p>S 老師不想你們為了她兩敗俱傷</p>        <p class="p_cls1">高老師總能分享出好東西</p>        <div class="div_cls3">            <p id="six_six_six">                我也退了,都怪我說了不該說的            </p>        </div>    </div>        """

我們看到此時就只獲取了第一個 div,注意:.div_cls1 和 .div_cls2 之間不可以有空格,如果加上了空格,那么含義就變成了選擇 .div_cls1 標簽下面的 .div_cls2 標簽。D4i28資訊網——每日最新資訊28at.com

所以 id、class、標簽等選擇器,它們可以搭配使用。比如說:D4i28資訊網——每日最新資訊28at.com

圖片圖片D4i28資訊網——每日最新資訊28at.com

實際舉例說明:D4i28資訊網——每日最新資訊28at.com

# 找到所有 class 包含 div_cls1、div_cls2 的標簽# 再從其兒子節點中找到所有 class 包含 .div_cls3 的 div 標簽print(p("div.div_cls1.div_cls2>div.div_cls3"))"""<div class="div_cls3">            <p id="six_six_six">                我也退了,都怪我說了不該說的            </p>        </div>        """

綜上所述,pyquery 還是很強大的。D4i28資訊網——每日最新資訊28at.com

選擇是否具有指定屬性的標簽

# 選擇具有 class 屬性的 p 標簽print(p("p[class]"))"""<p class="p_cls1">高老師總能分享出好東西</p>"""# 選擇具有 id 屬性的 p 標簽print(p("p[id]"))"""<p id="six_six_six">                我也退了,都怪我說了不該說的            </p>"""# 選擇 class="div_cls1" 的 div 標簽# 等號右面可以是雙引號,也可以是單引號,也可以不加引號print(p("div[class='div_cls1']"))"""<div class="div_cls1">        <span>嘿嘿嘿</span>    </div>"""# 注意:div[class='div_cls1'] 和 div.div_cls1 不同# 前者要求 class 屬性必須為 div_cls1# 而后者要求 class 屬性只要包含 div_cls1 即可# 這些屬性除了 id、class 之外, 也可以是其它的任意屬性(隨便寫一個也可以)# 下面選擇所有具有 href 屬性的 a 標簽print(p("a[href]"))"""<a />        <a # 選擇 href 等于某個 url 的 a 標簽, 這里的 url 必須要使用引號包起來print(p("a[<a # 還可以指定以 ... 開頭print(p("a[href^='http://www.me.org/image']"))"""<a # 指定以 ... 結尾print(p("a[href$='2.png']"))"""<a # 包含 ...print(p("a[href*='bento']"))"""<a # 當然其它屬性也可以,選擇 class 包含 div_cls1 的 a 標簽# 此時 div[class*='div_cls1'] 和 div.div_cls1 是等價的print(p("div[class*='div_cls1']") == p("div.div_cls1"))"""True"""

選擇指定位置的標簽

# 先選擇所有 class 包含 div_cls1、div_cls2 的標簽# 然后從它的兒子節點中選擇所有的 p 標簽print(p(".div_cls1.div_cls2>p"))"""<p>S 老師不想你們為了她兩敗俱傷</p>        <p class="p_cls1">高老師總能分享出好東西</p>"""# 先選擇所有 class 包含 div_cls1、div_cls2 的標簽# 然后從它的兒子節點中選擇所有 class 等于 p_cls1 的 p 標簽print(p(".div_cls1.div_cls2>p[class='p_cls1']"))"""<p class="p_cls1">高老師總能分享出好東西</p>"""# 然后也可以按照位置進行選擇,比如這里選擇符合條件的第一個 p 標簽print(p(".div_cls1.div_cls2>p:nth-child(1)"))"""<p>S 老師不想你們為了她兩敗俱傷</p>"""# 選擇符合條件的第二個 p 標簽print(p(".div_cls1.div_cls2>p:nth-child(2)"))"""<p class="p_cls1">高老師總能分享出好東西</p>"""

選擇兄弟標簽

# 選擇 class 包含 p_cls1 的所有 p 標簽,然后選擇它的兄弟標簽print(p("p.p_cls1").siblings())"""<p>S 老師不想你們為了她兩敗俱傷</p>        <div class="div_cls3">            <p id="six_six_six">                我也退了,都怪我說了不該說的            </p>        </div>"""

以上就是一些常見的 CSS 選擇器,在工作中一般是夠用了。D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

獲取標簽屬性

D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

基于 CSS 選擇器,我們可以拿到指定的標簽,然后就是獲取屬性了,比如獲取文本。D4i28資訊網——每日最新資訊28at.com

print(p("p").text())"""S 老師不想你們為了她兩敗俱傷 高老師總能分享出好東西 我也退了,都怪我說了不該說的"""

返回的是字符串,里面包含了所有的 p 標簽里的文本。但這樣我們就不知道,哪個文本是哪個 p 標簽里面的了,因此我們可以進行遍歷。D4i28資訊網——每日最新資訊28at.com

PyQuery 這個類繼承 list,因為基于選擇器篩選到的標簽可能會有多個,因此提供了用于遍歷的方法。但遍歷得到依舊是 PyQuery 對象,只不過此時里面就只有一個標簽了。D4i28資訊網——每日最新資訊28at.com

# 可以對選擇的標簽進行遍歷for tag in p("p").items():    print(tag.text())"""S 老師不想你們為了她兩敗俱傷高老師總能分享出好東西我也退了,都怪我說了不該說的"""

text 方法用于獲取文本,至于其它屬性則通過 attr 方法獲取。D4i28資訊網——每日最新資訊28at.com

for tag in p("a").items():    print(tag.attr("href"))"""http://www.me.org/bento/1.pnghttp://www.me.org/image/2.png"""for tag in p("div").items():    print(tag.attr("class"))"""div_cls1 div_cls2div_cls3Nonediv_cls1"""# 遍歷所有的標簽,獲取 id 的值for tag in p("*").items():    if tag.attr("id") is not None:        print(tag.attr("id"))"""six_six_six"""# 通過 attr 可以獲取所有的屬性,甚至自定義的也可以

是不是很方便呢?基于 CSS 選擇器和 attr 方法,我們就能獲取所有想要的屬性。D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

find 和 filter

D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

PyQuery 對象還有兩個很重要的方法,分別是 find 和 filter。D4i28資訊網——每日最新資訊28at.com

先來看看 find:D4i28資訊網——每日最新資訊28at.com

# p("div .div_cls3 p") 等價于 p.find("div").find(".div_cls3").find("p")# 或者也等價于 p.find("div").find(".div_cls3 p")# 也等價于 p.find("div .div_cls3").find("p")print(p("div .div_cls3 p") ==      p.find("div").find(".div_cls3").find("p") ==      p.find("div").find(".div_cls3 p") ==      p.find("div .div_cls3").find("p"))"""True"""# 相信你應該明白 find 方法是做什么的了,它是基于指定條件繼續向內篩選# 比如我們成功篩選了指定的標簽tag = p("div .div_cls3")# 這時候想在 tag 的基礎上繼續獲取它內部的 p 標簽,那么可以調用 findprint(tag.find("p"))"""<p id="six_six_six">                我也退了,都怪我說了不該說的            </p>"""

tag.find 是在 tag 的基礎上繼續向內篩選,而 tag.filter 則是對 tag 進行過濾。D4i28資訊網——每日最新資訊28at.com

tag = p("div p")# 在 tag 的基礎上向內篩選,獲取 class 包含 p_cls1 的標簽# 但 div p 內部沒有 class 包含 p_cls1 的標簽print(tag.find(".p_cls1"))""""""# 對 tag 進行過濾,從已獲取的 tag 中過濾出 class 包含 p_cls1 的標簽print(tag.filter(".p_cls1"))"""<p class="p_cls1">高老師總能分享出好東西</p>"""

所以當你篩選了指定的 div 之后,你想從它的內部繼續篩選,那么就使用 find 方法。如果你想按照指定條件對 div 進行過濾,那么就使用 filter。D4i28資訊網——每日最新資訊28at.com

另外 filter 還有一個用法,就是可以根據文本進行過濾。D4i28資訊網——每日最新資訊28at.com

print(p("p"))"""<p>S 老師不想你們為了她兩敗俱傷</p>        <p class="p_cls1">高老師總能分享出好東西</p>        <p id="six_six_six">                我也退了,都怪我說了不該說的            </p>        <p>            <a />        </p>"""# 對篩選到 p 標簽進行過濾,只保留文本包含 "老師" 的 p 標簽print(    p("p").filter(lambda _, this: "老師" in PyQuery(this).text()))"""<p>S 老師不想你們為了她兩敗俱傷</p>        <p class="p_cls1">高老師總能分享出好東西</p>"""

以上就是 find 和 filter 的用法,當你的解析需求不復雜時,直接調用 PyQuery 對象即可,否則可以搭配這兩個方法。D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

小結

D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

總的來說,pyquery 還是相當方便的,相比 bs4 多了更多的靈活性,而且速度也更快一些。D4i28資訊網——每日最新資訊28at.com

當然 pyquery 還有一些功能我們沒有說,比如追加節點等等,但這些不常用,所以不再贅述。因為我們只是解析 HTML,能基于選擇器獲取想要的標簽以及屬性就足夠了。D4i28資訊網——每日最新資訊28at.com

雖然 pyquery 是仿照 jquery 設計的,但我們不會像 jquery 操作 DOM 那樣,對節點進行新增修改啥的。我們要做的只有查詢,基于選擇器獲取指定標簽,并且選擇器也不止我們上面介紹的那些,不過基本上夠用了。D4i28資訊網——每日最新資訊28at.com

D4i28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-35879-0.htmlPyquery:一個靈活方便的 HTML 解析庫

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Redis哨兵模式,一主二仆反客為主,論故障轉移和恢復能力還得是它呀

下一篇: 13款開源圖片制作神器分享

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 东源县| 宝清县| 白山市| 淳安县| 焦作市| 仁化县| 东乌珠穆沁旗| 镇巴县| 北海市| 滕州市| 乐清市| 潢川县| 咸阳市| 威海市| 久治县| 休宁县| 赤壁市| 谢通门县| 贵德县| 镇康县| 宁化县| 宣城市| 福清市| 农安县| 绥中县| 黑龙江省| 泗洪县| 曲阜市| 孝义市| 辽宁省| 威远县| 海口市| 绥宁县| 郯城县| 印江| 招远市| 晴隆县| 兴城市| 上蔡县| 北海市| 霍城县|