Class 14 - 3 解析庫 -- pyquery

與Beautifu Soup 同樣,初始化 pyquery 的時候,也須要傳入 HTML 文原本初始化一個 PyQuery 對象。初始化方式有多種,如:直接傳入字符串,傳入 URL ,傳人文件名等。css

  1. 初始化
    • 字符串初始化  
      • 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></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('li'))
        輸出:
        <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>
        View Code

        引PyQuery對象,取別名爲 pq。聲明瞭一個長 HTML字符串,並將其看成參數傳遞給 PyQuery 類,這樣就成功完成了初始化。接下來,將初始化的對象傳入 css 選擇器。傳入 li 節點,這樣就可 選擇全部的 li 節點。  html

    • URL初始化
      • 初始化參數不只能夠以字符串的形式傳遞,能夠傳入網頁的URL,此時只須要指定參數爲 url 便可:
        from pyquery import PyQuery as pq
        doc =pq(url='https://cuiqingcai.com')
        print(doc('title'))
        輸出:
        <title>靜覓丨崔慶才的我的博客</title>&#13;
        View Code

        PyQuery 對象會首先請求這個 URL,用獲得的 HTML內容完成初始化,至關於用網頁的源代碼以字符串的形式傳遞給PyQuery 類來初始化。與如下功能相同:api

        from pyquery import PyQuery as pq
        import requests
        doc =pq(requests.get(url='https://cuiqingcai.com').text)
        print(doc('title'))
    • 文件初始化app

      • 除了傳遞 URL,還能夠傳遞本地的文件名,此時將參數指定爲filename便可:ide

        from pyquery import PyQuery as pq
        doc =pq(filename='demo.html')
        print(doc('li'))

        這裏須要有一個本地 HTML 文件 demo.html,其內容是待解析 HTML 字符串。它會首先讀取本地的文件內容,再用文件內容以字符串形式傳遞給PyQuery 類來初始化。ui

  2. 基本CSS選擇器
    • pyquery的CSS選擇示例:
      from pyquery import PyQuery as pq
      doc =pq('html')
      print(doc('#container .list li'))
      print(type(doc('#container .list li')))
      輸出:
      <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>
      
      <class 'pyquery.pyquery.PyQuery'>
      View Code

      初始化 PyQuery 對象後,傳入了 CSS 選擇器#container .list li ,意思是先選取 id container 的節點,而後再選取其內部的 class 爲list 的節點內部的全部 li 節點。而後輸出,成功獲取到了符合條件的節點。 它的類型依然是 PyQuery 類型。url

  3. 查找節點spa

    • 子節點3d

      • 查找子節點時,須要用到幹find()方法,此時傳人的參數是 CSS 選擇器。前面的 HTML 爲例:code

        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)
        輸出:
        <class 'pyquery.pyquery.PyQuery'>
        <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>
        
        <class 'pyquery.pyquery.PyQuery'>
        <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>
        View Code

        首先,選取 class 爲 list 的節點,再調用了 find()方法,傳入 CSS 選擇器,選取其內部 li 節點,最後輸出。find()方法會將符合條件的全部節點選擇出來,結果是 PyQuery 類型。

        其實find()的查找範圍是節點的全部子孫節點,若是隻想查找子節點,那麼能夠用 children()方法:

        lis = items.children()
        print(type(lis))
        print(lis)
        輸出:
        <class 'pyquery.pyquery.PyQuery'>
        <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>
        View Code

        若是要篩選全部子節點中符合條件的節點,如:篩選出子節點中 class 爲 active 節點,能夠向 children()方法傳入 CSS 選擇器 .active:

        lis = items.children('.active')
        print(lis)
        輸出:
        <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>
        View Code

        輸出結果已經作了篩選,留下了 class爲 active 的節點。

    • 父節點

      • 能夠用 parent()方法來獲取某個節點的父節點,示例:

        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.parent()
        print(type(container))
        print(container)
        輸出:
        <class 'pyquery.pyquery.PyQuery'>
        <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>
        View Code

        首先用 .list 選取 class爲 list 的節點,而後調用 parent()方法獲得其父節點,其類型依然是 PyQuery 類型。

        父節點是該節點的直接父節點,也就是說,它不會再去查找父節點的父節點, 即祖先節點  

        若是想獲取某個祖先節點,這時能夠用 parents()方法:

        from pyquery import PyQuery as pq
        doc=pq(html)
        items=doc('.list')
        parents =items.parents()
        print(parents)
        輸出:
        <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><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>
        View Code

        輸出結果有兩個:一個是 class爲wrap 的節點,一個是 id 爲 container 的節點。parents()方法會返回全部的祖先節點。

        若是想要篩選某個祖先節點,能夠向 parents()方法傳入 CSS 選擇器,這樣就會返回祖先節 點中符合 CSS 選擇器的節點:

        from pyquery import PyQuery as pq
        doc=pq(html)
        items=doc('.list')
        parent=items.parents('.wrap')
        print(parent)
        輸出:
        <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>
        View Code

        輸出結果只保留了 class 爲 wrap 的節點

    • 兄弟節點

      • 若是要獲取兄弟節點,可使用 siblings()方法。以上面 TML 爲例:

        from pyquery import PyQuery as pq
        doc =pq(html)
        li =doc('.list .item-0.active')
        print(li.siblings())
        輸出:
        <li class="item-1"><a href="link2.html">second item</a></li>
        <li class="item-0">first item</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>
        View Code

        首先選擇 class爲 list 的節點內部 class 爲 item-0 和 active 的節點,也就是第三個 li 節點。它的兄弟節點有 4 個,那就是第1、2、4、五個 li 節點。

        若是要篩選某個兄弟節點,依然能夠向 siblings 方法傳入 css 選擇器,這樣就會從全部兄弟節點中挑選符合條件的節點了:

        from pyquery import PyQuery as pq
        doc =pq(html)
        li =doc('.list .item-0.active')
        print(li.siblings(' .active'))
        輸出:
        <li class="item-1 active"><a href="link4.html">fourth item</a></li>

        篩選了 class 爲 active 的節點。

  4. 遍歷    

    • pyquery 選擇結果多是多個節點,也多是單個節點。都是PyQuery 類型,並無返回像 Beautiful Soup 那樣的列表。  

      對於單個節點來講,能夠直接打印輸出,也能夠直接轉成字符串

      from pyquery import PyQuery as pq
      doc = pq(html)
      li = doc('.item-0.active')
      print(li)
      print(str(li))
      輸出:
      <li class="item-0 active"><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>
      View Code

      對於多個節點的結果,就須要遍從來獲取。如,這裏把每個 li 節點進行遍歷,須要調用 items()方法:

      from pyquery import PyQuery as pq
      doc= pq(html)
      lis = doc('li').items()
      for li in lis:
          print(li,type(li))
      輸出:
      <li class="item-0">first item</li>
       <class 'pyquery.pyquery.PyQuery'>
      <li class="item-1"><a href="link2.html">second item</a></li>
       <class 'pyquery.pyquery.PyQuery'>
      <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
       <class 'pyquery.pyquery.PyQuery'>
      <li class="item-1 active"><a href="link4.html">fourth item</a></li>
       <class 'pyquery.pyquery.PyQuery'>
      <li class="item-0"><a href="link5.html">fifth item</a></li>
       <class 'pyquery.pyquery.PyQuery'>
      View Code

      調用 items()方法後, 會獲得生成器, 遍歷, 能夠逐個獲得 li 節點,也是PyQuery 類型。每一個 li 節點還能夠調用前面所說的方法進行選擇,如:繼續查詢子節點,尋找某個祖先節點等。

  5. 獲取信息  

    • 提取節後,最終目是提取節點所包含的信息。比較重要的信息有兩類,一是獲取屬’性,二是獲取文本

    • 獲取屬性
      • 提取到某個 PyQuery 類型的節點後,就能夠調用 attr ()方法來獲取屬性:
        from pyquery import PyQuery as pq
        doc =pq(html)
        a=doc('.item-0.active a')
        print(a,type(a))
        print(a.attr('href'))
        輸出:
        <a href="link3.html"><span class="bold">third item</span></a> <class 'pyquery.pyquery.PyQuery'>
        link3.html
        View Code

        首先選中 class 爲 item-0 和 active 的 li 節點內的 a 節點,是 PyQuery 類型。而後調用 attr()方法。在這個方法中傳入屬性的名稱,就能夠獲得這個屬性值了。

        也能夠經過調用 attr 屬性來獲取屬性,用法:
        print(a.attr.href)
        輸出:
        link3.html

        這兩種方法的結果徹底同樣。

        若是選中的是多個元素,而後調用 attr()方法:
        from pyquery import PyQuery as pq
        doc = pq(html)
        a = doc('a')
        print(a,type(a))
        print(a.attr('href'))
        print(a.attr.href)
        輸出:
        <a href="link2.html">second item</a><a href="link3.html"><span class="bold">third item</span></a><a href="link4.html">fourth item</a><a href="link5.html">fifth item</a> <class 'pyquery.pyquery.PyQuery'>
        link2.html
        link2.html
        View Code

        選中的 a 節點應該有 4個,並且打印結果也應該是 4 個,可是當咱們調用 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
        View Code

        在進行屬性獲取時,能夠觀察返回節點是一個仍是多個,若是是多個, 須要遍歷才能依次獲取每一個節點的屬性。

    • 獲取文本
      • 獲取節點後的另外一個主要操做就是獲取其內部的文本,此時能夠調用 text()方法來實現:
        from pyquery import PyQuery as pq
        doc =pq(html)
        a =doc('.item-0.active a')
        print(a)
        print(a.text()
        輸出:
        <a href="link3.html"><span class="bold">third item</span></a>
        third item
        View Code

        這裏首先選中一個 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 class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
        
        <a href="link3.html"><span class="bold">third item</span></a>
        View Code

        這裏咱們選中了第三個 li 節點,而後調用了 html()方法,返回的結果應該是 li 節點內的全部 HTML 文本。

        若是選中的結果是多個節點, text()或 html()返回結果各不相同,實例:
        from pyquery import PyQuery as pq
        doc = pq(html)
        li =doc('li')
        print(li.html())
        print(li.text())
        print(type(li.text()))
        輸出:
        first item
        first item second item third item fourth item fifth item
        <class 'str'>
        View Code

        html()方法返回的是第一個 li 節點的內部 HTML 文本,而 text()返回全部 li 節點內部的純文本,中間用 個空格分割開,即返回結果是一個字符串。

        注意:若是獲得的結果是多個節點,且想要獲取每一個節點的內部 HTML 文本, 則須要遍歷每一個節點。text ()方法不須要遍歷就能夠獲取,它將全部節點取文本以後合併成 一個字符串。
  6. 節點操做
    • pyquery 提供了一系列方法來對節點進行動態修改,如爲某個節點添加一個 class,移除某個節點等,例:
    • addClass()和 removeClass()方法能夠動態改變節點的 class 屬性
      • 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)
        輸出:
        <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>
        View Code

        首先選中了第三個 li 節點,而後調用 removeClass()方法,將 li 節點的 active 這個 class 移除,後來在調用 addClass()方法,將 class 添加回來。每執行一次操做,就打印輸出當前 li 節點的內容

    • attr()、text() 和 html() 方法對屬性進行操做,來改變節點內部的內容。 示例: 

      • 若是 attr()方法只傳入第一個參數的屬性名,則是獲取這個屬性值; 若是傳入第二個參 數,能夠用來修改屬性值。 text()和 html()方法若是不傳參數,則是獲取節點內純文本和 HTML 文本; 若是傳人蔘數,則進行賦值。

      • html = '''
        <ul class="list">
        <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
        </ul>
        '''
        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('<span>changed item</span>')
        print(li)
        輸出:
        <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
        
        <li class="item-0 active" name="link"><a href="link3.html"><span class="bold">third item</span></a></li>
        
        <li class="item-0 active" name="link">changed item</li>
        
        <li class="item-0 active" name="link"><span>changed item</span></li>
        View Code

        首先選中 li 節點,而後調用 attr()方法來修改屬性,該方法的第一個參數爲屬性名,第二個參數爲屬性值。 接着,調用 text()和 html()方法來改變節點內部的內容。三次操做後,分 別打印輸出當前的 li 節點。

        調用 attr()方法後,li 節點多了一個本來不存在的屬性 name, 其值爲 link。 接着調 用 text()方法,傳人文本以後, li 節點內部的文本全被改成傳人的字符串文本了。 最後,調用 html() 方法傳人 HTML 文本後 li 節點內部又變爲傳人的 HTML 文本了。

    • remove()
      • html = '''
        <div class="wrap">
            Hello,World
        <p>This is a paragraph.</p>
        </div>
        '''
        from pyquery import PyQuery as  pq
        doc =pq(html)
        wrap = doc('.wrap')
        print(wrap.text())
        輸出:
        Hello,World
        This is a paragraph.
        View Code

        由於text()把全部的存文本都提取出來,若是須要提取Hello,world這個字符串,而不須要P節點內部的字符串,可以使用remove.

        from pyquery import PyQuery as  pq
        doc =pq(html)
        wrap = doc('.wrap')
        wrap.find('p').remove()
        print(wrap.text())
        輸出:
        Hello,World

        首先選中 p 節點,而後調用了 remove()方法將其移除,這時 wrap 內部就只剩下 Hello, World 這句話了,再利用 text()方法提取便可。 

        實還有不少節點操做的方法,好比 append()、 empty()和 prepend()等方法, jQuery 的用法徹底一致,詳細的用法能夠參考官方文檔: http://pyquery.readthedocs.io/en/latest/api.html
  7. 僞類選擇器
    • CSS 選擇器之因此強大,就是它支持多種多樣的僞類選擇器,如:選擇第一個節點、最後一個節點、奇偶數節點、包含某一文本的節點等。 示例:
      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)
      輸出:
      <li class="item-0">first item</li>
      
      <li class="item-0"><a href="link5.html">fifth item</a></li>
      
      <li class="item-1"><a href="link2.html">second item</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>
      
      <li class="item-1"><a href="link2.html">second item</a></li>
      <li class="item-1 active"><a href="link4.html">fourth item</a></li>
      
      <li class="item-1"><a href="link2.html">second item</a></li>
      View Code

      這裏使用 CSS3 的僞類選擇器,依次選擇了第一個 li 節點、最後一個 li 節點 、第二個 li 節點、第三個 li 以後的 li 節點、 偶數位置的 li 節點、 包含 second 文本的 li 節點。關於 css 選擇器的更多用法,能夠參考 http://www.w3school.com.cn/css/index.asp。更多內容,能夠參考 pyquery 的官方文 檔: http://pyquery.readthedocs.io

                
相關文章
相關標籤/搜索