<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python爬蟲:一篇文章教你學(xué)會pyquery

          共 21068字,需瀏覽 43分鐘

           ·

          2021-08-12 02:17

          什么是pyquery

          pyquery是類似于jquery的網(wǎng)頁解析工具,讓你使用jquery的風(fēng)格來遍歷xml文檔,它使用lxml操作html的xml文檔,它的語法與jquery很像,和我們之前所講的解析庫xpath與Beautiful Soup比起來更加靈活與簡便,并且增加了添加類和移除節(jié)點的操作,這些操作有時會為提取信息時帶來極大的便利。

          使用pyquery

          如果你對web有所了解,并且比較喜歡使用CSS選擇器,那么這里有一款更適合你的解析庫——jquery。

          準(zhǔn)備工作

          在使用之前,請確保已經(jīng)安裝好qyquery庫。安裝教程如下所示:

          pip install pyquery

          初始化

          和Beautiul Soup一樣,在初始化pyquery的時候,也需要傳入html文本來初始化一個pyquery對象。

          初始化的時候一般有三種傳入方式:傳入字符串、傳入URL、傳入html文件。

          • 字符串初始化
          html = '''
          <div>
              <ul>
                  <li class="item-0">first-item</li>
                  <li class="item-1"><a href="link2.html">second item</a></li>
                  <li class="item=-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                  <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                  <li class="item-0"><a href="link5.html">fifth item</a></li>        
              </ul>
          </div>
          '''


          from pyquery import PyQuery as pq


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

          先對上面的代碼做簡單的描述:

          首先引入PyQuery對象,取名為pq。然后聲明一個長HTML字符串,并將其當(dāng)作參數(shù)傳給PyQuery類,這樣就成功的進(jìn)行了初始化。

          接下來將css選擇器作為參數(shù)傳入初始化對象,在這個示例中我們傳入li節(jié)點,這樣就可以選擇所有的li節(jié)點.。

          • URL初始化

          初始化對象的參數(shù)不僅可以是字符串,還可以是網(wǎng)頁的URL,這時可以將URL作為參數(shù)傳入初始化對象。

          具體代碼如下所示:

          from pyquery import PyQuery as pq


          doc = pq('https://www.baidu.com', encoding='utf-8')
          print(doc)
          print(type(doc))
          print(doc('title'))

          試著運行上面的代碼你會發(fā)現(xiàn),我們成功的獲取到了百度的title節(jié)點和網(wǎng)頁信息。

          PyQuery對象會先請求這個URL,然后用得到的HTML內(nèi)容完成初始化,這其實就相當(dāng)于網(wǎng)頁源代碼以字符串的形式傳遞給初始化對象。

          因此,還可以這樣寫代碼:

          from pyquery import PyQuery as pq
          import requests


          url = 'https://www.baidu.com'
          doc = pq(requests.get(url).content.decode('utf-8'))
          print(doc)
          print(type(doc))
          print(doc('title'))

          運行結(jié)果與上面那段代碼的運行結(jié)果是一致的。

          • 文件初始化

          除了傳遞URL以外還可以傳遞本地的文件名,此時只要傳遞本地文件名,此時將參數(shù)指定為filename即可。

          具體代碼如下所示:

          from pyquery import PyQuery as pq


          doc = pq(filename='baidu.html')
          print(doc)
          print(type(doc))
          print(doc('title'))

          以上三種初始化的方式都是可以的,當(dāng)然最常用的初始化方式還是以字符串的形式傳遞。

          基本CSS選擇器

          html = '''
          <div id="container">
              <ul class="list">
                  <li class="item-0">first-item</li>
                  <li class="item-1"><a href="link2.html">second item</a></li>
                  <li class="item=-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                  <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                  <li class="item-0"><a href="link5.html">fifth item</a></li>        
              </ul>
          </div>
          '''


          from pyquery import PyQuery as pq


          doc = pq(html)
          print(doc('#container .list li'))
          print(type(doc('#container .list li')))

          初始化PyQuery對象之后,傳入CSS選擇器#container .list li將所有符合條件的節(jié)點輸出,并且運行上面的代碼之后你會發(fā)現(xiàn)它的類型依然還是PyQuery類型。

          查找節(jié)點

          下面介紹一些常用的查詢函數(shù),這些函數(shù)與jQuery函數(shù)的用法是完全相同的。

          • 子節(jié)點

          查找子節(jié)點時需要用到find()方法,并傳入的參數(shù)是CSS選擇器,以前面的html為例子。

          from pyquery import PyQuery as pq


          doc = pq(html)
          print(doc.find('li'))
          print(type(doc.find('li')))

          調(diào)用find()方法,將節(jié)點名稱li傳入該方法,獲取所有符合條件的內(nèi)容。類型依然還是PyQuery。

          當(dāng)然我們還可以這樣寫:

          from pyquery import PyQuery as pq


          doc = pq(html)
          items = doc('.list')
          print(type(items))
          lis = items.find('li')
          print(type(lis))
          print(lis)

          首先先選取class為list的節(jié)點,然后調(diào)用find()方法,傳入CSS選擇器,選取內(nèi)部的``li`節(jié)點,最后打印輸出。

          其實find()方法是查找所有的子孫節(jié)點,要獲取所有的子節(jié)點可以調(diào)用chirdren()方法。具體代碼如下所示:

          from pyquery import PyQuery as pq


          doc = pq(html)
          items = doc('.list')
          lis = items.children()
          print(lis)
          print(type(lis))

          如果想要篩選子節(jié)點中符合條件的節(jié)點,可以向chirdren()方法傳入CSS選擇器。具體代碼如下所示:

          from pyquery import PyQuery as pq


          doc = pq(html)
          items = doc('.list')
          lis = items.children('.active')
          print(lis)
          print(type(lis))

          試著運行上面的代碼你會發(fā)現(xiàn),這里已經(jīng)成功獲取到了class為active的節(jié)點。

          • 父節(jié)點

          我們可以調(diào)用parent()方法來獲取某個節(jié)點的父節(jié)點。

          html = '''
          <div id="container">
              <ul class="list">
                  <li class="item-0">first-item</li>
                  <li class="item-1"><a href="link2.html">second item</a></li>
                  <li class="item=-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                  <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                  <li class="item-0"><a href="link5.html">fifth item</a></li>        
              </ul>
          </div>
          '''


          from pyquery import PyQuery as pq


          doc = pq(html)
          items = doc('.list')
          container = items.parent()
          print(container)
          print(type(container))

          先對上面的代碼做簡要的說明:

          首先選取class為list的節(jié)點,然后再調(diào)用parent()方法得到其父節(jié)點,其類型依然還是PyQuery類型。

          這里的父節(jié)點是直接父節(jié)點,但是如果要獲取祖父節(jié)點,可以調(diào)用parents()方法。

          html = '''
          <div class="wrap">
              <div id="container">
                  <ul class="list">
                      <li class="item-0">first-item</li>
                      <li class="item-1"><a href="link2.html">second item</a></li>
                      <li class="item=-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                      <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                      <li class="item-0"><a href="link5.html">fifth item</a></li>        
                  </ul>
              </div>

          </div>

          '''


          from pyquery import PyQuery as pq


          doc = pq(html)
          items = doc('.list')
          container = items.parents()
          print(container)
          print(type(container))

          運行上面的代應(yīng)為碼之后,你會發(fā)現(xiàn)這里輸出的內(nèi)容有四個,因為class為list節(jié)點的祖父節(jié)點有四個,分別是:container、wrap、body、html。在初始化對象的時候已經(jīng)添加上了body和html節(jié)點。

          • 兄弟節(jié)點

          除了可以獲取到父節(jié)點和子節(jié)點之外,還可以獲取到兄弟節(jié)點。如果需要獲取兄弟節(jié)點,可以調(diào)用siblings()方法。

          具體代碼如下所示:

          html = '''
          <div class="wrap">
              <div id="container">
                  <ul class="list">
                      <li class="item-0">first-item</li>
                      <li class="item-1"><a href="link2.html">second item</a></li>
                      <li class="item-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                      <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                      <li class="item-0"><a href="link5.html">fifth item</a></li>        
                  </ul>
              </div>

          </div>

          '''


          from pyquery import PyQuery as pq


          doc = pq(html)
          items = doc('.list .item-0.active')
          print(items.siblings())

          這里首先選取類為.item-0.active的節(jié)點,再調(diào)用siblings()方法獲取到該節(jié)點的兄弟節(jié)點。

          試著運行上面的代碼,你會發(fā)現(xiàn)獲取到其他四個兄弟節(jié)點。

          遍歷

          通過上面的代碼可以觀察到,pyquery的選擇結(jié)果可能是多個節(jié)點,也可能是單個節(jié)點,類型都是PyQuery類型,并沒有向Beautiful Soup那樣的列表。

          對于單個節(jié)點來說,可以直接打印輸出,也可以直接轉(zhuǎn)成字符串。

          from pyquery import PyQuery as pq


          doc = pq(html)
          items = doc('.list .item-0.active')
          print(items)
          print(str(items))
          print(type(items))

          對于多個節(jié)點,可以通過調(diào)用item()方法,將獲取的內(nèi)容轉(zhuǎn)換成生成器類型,在通過遍歷的方式輸出。

          具體代碼如下所示:

          from pyquery import PyQuery as pq


          doc = pq(html)
          lis = doc('li').items()
          print(lis)
          for li in lis:
              print(li, type(li))

          運行上面的代碼,你會發(fā)現(xiàn)輸出變量lis的結(jié)果是生成器,因此可以遍歷輸出。

          獲取信息

          一般來說,在網(wǎng)頁里面我們需要獲取的信息有兩類:一類是文本內(nèi)容,另一類是節(jié)點屬性值。

          • 獲取屬性

          獲取到某個PyQuery類型的節(jié)點之后,就可以通過attr()方法來獲取屬性。

          具體代碼如下所示:

          from pyquery import PyQuery as pq


          doc = pq(html)
          a = doc('.list .item-0.active a')
          print(a.attr('href'))

          先獲取class為list下面的class為item-0 active的節(jié)點下的a節(jié)點,這時變量a是PyQuery類型,再調(diào)用attr()方法并傳入屬性值href

          當(dāng)然也可以通過調(diào)用attr屬性來獲取屬性。

          print(a.attr.href)

          你會發(fā)現(xiàn)輸出結(jié)果與上面的代碼是一樣的。

          當(dāng)然,我們也可以獲取到所有a節(jié)點的屬性,具體代碼如下所示:

          html = '''
          <div class="wrap">
              <div id="container">
                  <ul class="list">
                      <li class="item-0">first-item</li>
                      <li class="item-1"><a href="link2.html">second item</a></li>
                      <li class="item-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                      <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                      <li class="item-0"><a href="link5.html">fifth item</a></li>        
                  </ul>
              </div>

          </div>

          '''


          from pyquery import PyQuery as pq


          doc = pq(html)
          a = doc('a').items()
          for item in a:
              print(item.attr('href'))

          但是如果代碼這樣寫:

          from pyquery import PyQuery as pq


          doc = pq(html)
          a = doc('a')
          print(a.attr('href'))

          運行上面的代碼之后,你會發(fā)現(xiàn)只獲取到第一個a節(jié)點的href屬性。

          所有這個是需要注意的地方!!

          • 提取文本

          提取文本與提取屬性的邏輯是一樣的,首先獲取到class為PyQuery的節(jié)點,再調(diào)用text()方法獲取文本。

          首先來獲取一個節(jié)點的文本內(nèi)容。具體代碼如下所示:

          html = '''
          <div class="wrap">
              <div id="container">
                  <ul class="list">
                      <li class="item-0">first-item</li>
                      <li class="item-1"><a href="link2.html">second item</a></li>
                      <li class="item-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                      <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                      <li class="item-0"><a href="link5.html">fifth item</a></li>        
                  </ul>
              </div>

          </div>

          '''


          from pyquery import PyQuery as pq


          doc = pq(html)
          a = doc('.list .item-0.active a')
          print(a.text())

          試著運行上面的代碼你會發(fā)現(xiàn)成功獲取a節(jié)點的文本內(nèi)容。

          接下來我們就來獲取多個li節(jié)點的文本內(nèi)容。

          具體代碼如下所示:

          html = '''
          <div class="wrap">
              <div id="container">
                  <ul class="list">
                      <li class="item-0">first-item</li>
                      <li class="item-1"><a href="link2.html">second item</a></li>
                      <li class="item-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                      <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                      <li class="item-0"><a href="link5.html">fifth item</a></li>        
                  </ul>
              </div>

          </div>

          '''


          from pyquery import PyQuery as pq


          doc = pq(html)
          items = doc('li')
          print(items.text())

          運行上面的代碼,你會發(fā)現(xiàn)該代碼成功獲取到了所有節(jié)點名稱為li的文本內(nèi)容,中間用空格隔開。

          如果你想要一個一個獲取,那還是少不了生成器,具體代碼如下所示:

          from pyquery import PyQuery as pq


          doc = pq(html)
          items = doc('li').items()
          for item in items:
              print(item.text())

          節(jié)點操作

          pyquery提供了一系列方法對節(jié)點進(jìn)行動態(tài)修改,比如為某個節(jié)點添加一個class,移除某個節(jié)點,這些操作有時會為提取信息帶來便利。

          • add_class和remove_class
          html = '''
          <div class="wrap">
              <div id="container">
                  <ul class="list">
                      <li class="item-0">first-item</li>
                      <li class="item-1"><a href="link2.html">second item</a></li>
                      <li class="item-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                      <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                      <li class="item-0"><a href="link5.html">fifth item</a></li>        
                  </ul>
              </div>

          </div>

          '''


          from pyquery import PyQuery as pq


          doc = pq(html)
          li = doc('.list .item-0.active')
          print(li)
          li.remove_class('active')
          print(li)
          li.add_class('active')
          print(li)

          運行結(jié)果如下所示:

          <li class="item-0 active"><a href="link3.html"><span class="" bold="">third item</span></a></li>
                      
          <li class="item-0"><a href="link3.html"><span class="" bold="">third item</span></a></li>
                      
          <li class="item-0 active"><a href="link3.html"><span class="" bold="">third item</span></a></li>

          上面有三段輸出內(nèi)容,首先先獲取一個li節(jié)點,然后再刪除active類屬性,第三段代碼是添加active類屬性。

          偽類選擇器

          CSS選擇器之所以強大,還有一個很重要的原因,那就是它可以支持多種多樣的偽類選擇器,例如選擇第一個節(jié)點、最后一個節(jié)點、奇偶數(shù)節(jié)點、包含某一文本的節(jié)點。

          html = '''
          <div class="wrap">
              <div id="container">
                  <ul class="list">
                      <li class="item-0">first-item</li>
                      <li class="item-1"><a href="link2.html">second item</a></li>
                      <li class="item-0 active"><a href="link3.html"><span class=""bold>third item</span></a></li>
                      <li class="item-1 active"><a href="link4.html">fourth item</a></li>
                      <li class="item-0"><a href="link5.html">fifth item</a></li>        
                  </ul>
              </div>

          </div>

          '''


          from pyquery import PyQuery as pq


          doc = pq(html)
          li = doc('li:first-child'# 第一個li節(jié)點
          print(li)
          li = doc('li:last-child'# 最后一個li節(jié)點
          print(li)
          li = doc('li:nth-child(2)'# 第二個位置的li節(jié)點
          print(li)
          li = doc('li:gt(2)'# 第三個之后的li節(jié)點
          print(li)
          li = doc('li:nth-child(2n)'# 偶數(shù)位置的li節(jié)點
          print(li)
          li = doc('li:contains(second)'# 包含second文本的li節(jié)點
          print(li)

          至此,關(guān)于pyquery的所有內(nèi)容都講完了,接下來就進(jìn)入實戰(zhàn)了,光說不練肯定是不行的,只有通過實戰(zhàn)才能正真學(xué)會剛剛所學(xué)會的知識。

          實戰(zhàn)

          本次我?guī)淼膶崙?zhàn)內(nèi)容是爬取貓眼電影的TOP100的排行榜及評分情況。

          準(zhǔn)備

          工欲善其事,必先利其器。首先,我們要準(zhǔn)備幾個庫:pyquery、requests。

          安裝過程如下:

          pip install pyquery
          pip install requests

          前言

          寒假又到來了,小伙伴們準(zhǔn)備怎么過呢?

          在大冬天里,躲在被窩刷劇是最舒服的,好懷念當(dāng)年的生活啊~

          所以今天就來爬取貓眼電影的TOP100排行榜,為冬眠做好準(zhǔn)備。

          網(wǎng)站鏈接:

          https://maoyan.com/board/4

          需求分析與功能實現(xiàn)

          獲取電影名稱

          從上圖可以看到我們需要的信息藏在class為board-item-maindiv標(biāo)簽下的a標(biāo)簽內(nèi),因此我們需要獲取其文本信息。

          核心代碼如下所示:

          movie_name = doc('.board-item-main .board-item-content .movie-item-info p a').text()

          獲取主演信息

          從上圖可以看到,主演的信息位于board-item-main的子節(jié)點p標(biāo)簽內(nèi),因此我們可以這樣獲取主演信息。

          核心代碼如下所示:

          p = doc('.board-item-main .board-item-content .movie-item-info')
          star = p.children('.star').text()

          獲取上映時間

          從前面的圖片也可以看到,上映時間的信息與主演信息的節(jié)點是兄弟節(jié)點,所以我們可以這樣寫代碼。

          p = doc('.board-item-main .board-item-content .movie-item-info')
          time = p.children('.releasetime').text()

          獲取評分

          要獲取每一部電影的評分相對要復(fù)雜一些,為什么這樣說呢?我們來看下面的圖片。

          從上面的圖片可以看到,整數(shù)部分與小數(shù)部分被分割了成了兩部分。因此需要分別獲取兩部分的數(shù)據(jù),在進(jìn)行拼接即可。

          核心代碼如下所示:

          score1 = doc('.board-item-main .movie-item-number.score-num .integer').text().split()
          score2 = doc('.board-item-main .movie-item-number.score-num .fraction').text().split()
          score = [score1[i]+score2[i] for i in range(0, len(score1))]

          關(guān)于翻頁

          打開網(wǎng)頁的時候,你會發(fā)現(xiàn)榜單一共有10頁,每一頁的URL都不相同,那該怎么辦呢?總不能每一次都手動更換URL地址吧。

          先來觀察前四頁的URL地址吧。

          https://maoyan.com/board/4 # 第一頁
          https://maoyan.com/board/4?offset=10 # 第二頁
          https://maoyan.com/board/4?offset=20 # 第三頁
          https://maoyan.com/board/4?offset=30 # 第四頁

          觀察完之后,我想不需要我過多敘述它的特點了吧。

          接下來我們就可以構(gòu)建每一頁的URL地址了,具體代碼如下所示:

              def get_url(self, page):
                  url = f'https://maoyan.com/board/4?offset={page}'
                  return url
              if __name__ == '__main__':
              maoyan = MaoYan()
              for page in range(10):
                  url = maoyan.get_url(page*10)

          結(jié)果展示

          最后

          本次分享到就此結(jié)束,如果你從開頭讀到這里,想必文章對你是有所幫助的,這也是我分享知識的初衷。

          掃一掃下面的二維碼,回復(fù):貓眼獲取代碼!

          沒有什么是可以一蹴而就的,生活如此,學(xué)習(xí)亦是如此!

          路漫漫其修遠(yuǎn)兮,吾將上下而求索

          們的文章到此就結(jié)束啦,如果你喜歡今天的Python 實戰(zhàn)教程,請持續(xù)關(guān)注Python實用寶典。

          有任何問題,可以在公眾號后臺回復(fù):加群,回答相應(yīng)紅字驗證信息,進(jìn)入互助群詢問。

          Python實用寶典 (pythondict.com)
          不只是一個寶典
          歡迎關(guān)注公眾號:Python實用寶典

          瀏覽 30
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕操逼视频 | 中文字幕第一区 | 五月天婷婷影院 | 成人午夜网站 | 99久久精品国产色欲 |