整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          從0學爬蟲-頁面解析的幾種方法

          從0學爬蟲-頁面解析的幾種方法

          話不多說,直接進入正題。

          一。首先是xpath。

          1.官方的來講就是能在xml樹狀結構中尋找節點 xpath用于在xml文檔中通過元素和屬性進行導航和定位。

          2.解析網頁,對于一些網頁結構比較明顯的我們一般都采用xpath去進行解析。

          3.快速入門

          from lxml import etree
          # html網頁源代碼
          html="""
                  <div>
                      <ul>
                           <li class="item-0"><a href="link1.html">first item</a></li>
                           <li class="item-1"><a href="link2.html">second item</a></li>
                           <li class="item-inactive"><a href="link3.html">third item</a></li>
                           <li class="item-1"><a href="link4.html">fourth item</a></li>
                           <li class="item-0"><a href="link5.html">fifth item</a>
                       </ul>
                   </div>
                  """
          # 將html轉成xml
          element=etree.HTML(html)
          # print(element)
          # 獲取li標簽下面的a標簽的href屬性值
          links=element.xpath('//ul/li/a/@href')
          print(links)  # 列表
          # 獲取li標簽下面的a標簽的文本數據
          titles=element.xpath('//ul/li/a/text()')
          print(titles)

          結果如下:

          二。BS4

          BS4也是一種解析方式,原理基本類似xpath。兩者相對比,xpath需要記住一些語法,bs4則只需要記住一些方法就可以了,掌握Beautifulsoup這個核心類就ok了

          ● 安裝

          ○ pip install lxml

          ○ pip install bs4 bs4這個庫對我們的lxml存在依賴

          詳細使用可以參考中文文檔地址:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/

          一般常用的find_all和find就能應對大部分情況。

          import requests
          from bs4 import BeautifulSoup
          #解析
          soup=BeautifulSoup(text,'html5lib') #這里一般采用 lxml ,也可以使用html5lib
          #獲取單個標簽
          aa=soup.find('div', id="container")
          #獲取標簽下所有的下一級標簽
          list=aa.find_all('div', class_="box picblock col3")

          三。urllib

          保存圖片很好用,其他情況使用不多。

          獲取請求示例:

          import urllib.request
          url='需要訪問的網頁地址'
          headers={
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
          }
          # 1 創建req請求對象并構建headers
          req=urllib.request.Request(url,headers=headers)
          print(req)  # <urllib.request.Request object at 0x0000022D35B9BB88>
          # 2 獲取響應數據
          response=urllib.request.urlopen(req)
          # 3 讀取響應內容
          html=response.read().decode('utf-8')
          print(html)

          保存圖片示例:

          是入門理論的最后一部分,完成了這一步就可以說是完成了一個簡單的爬蟲。用來解析響應中的Html文件的Python模塊由很多,解析方式也有所不同。據我觀察beautifulsoup的使用應該比lxml更加普及(我沒有做過系統的調查,這個結果是根據查找到的資料數量來的),但是如何選擇還要看使用者自己的喜好。

          beautifulsoup(bs4)

          beautifulsoup(下稱bs4)使用Python編寫,使用相較于lxml較容易,但是效率也較低。不過bs4支持很多解析器,lxml也是其中一種。

          1 解析器

          上文說到bs4支持很多解析器,我們在此列出:

          -Python自帶的標準庫“html.parser”:因為是內置的庫所以使用簡單,但在Python2.7.3/3.2.2之前容錯能力差

          -lxml解析器“lxml”:速度快容錯高,但是需要安裝C語言庫

          -lxmlXML解析器“lxml-xml”/“xml”:速度快支持XML,也需要安裝C語言庫

          -html5lib解析器“html5lib”:速度慢但會以瀏覽器的形式解析文檔

          至于bs4解析HTML文檔只需要小小的一步:

          from bs4 import BeautifulSoup
          soup_html=BeautifulSoup(你的html文本,"解析器,也就是我剛剛介紹里的粗體部分,也可以不填讓bs4自己選擇")

          2 四類對象

          bs4會將html文本轉換成一個樹形結構,而結構里的對象有四種,分別是Tag(標簽)、NavigableString(字符串)、BeautifulSoup和Comment(注釋)。下面我們分別解釋這四類對象在html文本中的含義。

          -Tag:tag的意思就是標簽,它與html文本中的標簽同義。BeautifulSoup對象也可以被看做是一個Tag。Tag中屬性的訪問方法如同字典,比如訪問Tag對象a的href屬性的寫法為a[‘href’]。

          -NavigableString:html文本中所有的字符內容(就是除了標簽之外被直接展示出來的文字)都是NavigableString。

          -BeautifulSoup:它就是完整的一個html文本,可以被看做一個特殊的Tag。

          -Comment:注釋,也可以被當做NavigableString被.string訪問到。

          判斷一個子節點對象類型的方法:type(soup_html)==bs4.element.對象名

          3 篩選函數

          在將html文本轉換成對象樹之后,bs4會提供一系列方法來查詢它們。下面會列舉出一些常用的方法。

          -BeautifulSoup.prettify():得到格式化的標準縮進的html文本。

          -Tag.Tagname:用.運算符會返回第一個標簽名為Tagname的標簽。

          -Tag.name:返回此標簽的名字(按照這個寫法可能有點多余,但是如果是你不知道標簽名的soup呢?)

          -Tag.contents:獲得所有子標簽的列表。

          -Tag.parents:獲得所有父標簽的列表。

          -Tag.string:獲得標簽內部的文字。(只在標簽內僅有一個NavigableString對象的時候返回值,否則為None)

          -Tag.strings:獲得所有文字列表。

          -Tag.stripped_strings:獲得去掉換行符和空格的文字列表。

          -Tag.Tagname[‘Attrname’]:返回第一個Tagname標簽的Attrname屬性的值。

          -Tag.find(attr=”attrname”[,”tagname”]):這個方法查找第一個符合條件的標簽其屬性attr值等于attrname。

          -Tag.find_all(attr=”attrname”[,]):同上,不過返回的是所有符合條件的標簽。對于find與find_all函數,當attr為class時需要寫作class_,這是為了避開保留字。

          lxml

          相較于beautifulsoup而言lxml使用C語言編寫(而且beautifulsoup一次要讀取整個DOM),所以在運行效率和速度等方面lxml是當之無愧的優勢。但是lxml采用XPath解析HTML和XML文件,所以如果要用lxml對HTML進行解析還要先學習XPath。

          1 XPath

          XPath全稱為XML Path Language,也就是XML路徑(解析)語言。顧名思義它最初被設計用于XML文件的搜索,但是現在也支持HTML。

          學習XPath的成本(初步運用)應與學習正則表達式類似。(這是個人觀點)

          2 XPath基本常用語法

          關于XPath的概念等我們限于篇幅就不展示了,請自行尋找資料學習。以下列出的是在爬蟲領域較為常用的語法。

          -nodename:選取nodename節點的所有子節點

          -/:選取根節點

          -//:從當前節點選取任意位置節點

          -.:選取當前節點

          -..:選取當前節點的父節點

          -@:選取屬性

          -[]:XPath中的“謂語”,也就是查找條件

          -*:匹配任何元素節點

          -@*:匹配任何屬性節點

          -node():匹配任何節點

          -text():獲取文本內容

          3 lxml解析html

          from lxml import etree
          html_lxml=etree.HTML(html) #將html文本變成lxml的對象
          html_lxml.xpath("XPath表達式") #用XPath搜索對象

          4 例 XPath的運用

          以bs4官網教程里的一段html(愛麗絲文檔)為例,我將寫出這段文本里部分元素節點的XPath以供讀者參考。你也可以使用chrome的開發者工具->copy->copyXPath獲得頁面中標簽的XPath。

          義上講,爬蟲只負責抓取,也就是下載網頁。而實際上,爬蟲還要負責從下載的網頁中提取我們想要的數據,即對非結構化的數據(網頁)進行解析提取出結構化的數據(有用數據)。

          所以說,網頁下載下來只是第一步,還有重要的一步就是數據提取。不同的爬蟲想要的數據不一樣,提取的數據也就不一樣,但提取方法都是類似的。

          最簡單的提取數據的方法,就是使用正則表達式,此種方法簡單,提取的邏輯也不能復雜,不然寫出的正則表達式就晦澀難懂,甚至不能提取復雜的數據結構。

          最終,老猿經過多年的使用經驗,選擇了lxml和xpath來解析網頁提取結構化數據。順便說一下 BeautifulSoup,它也是一個很棒的解析HTML的工具,可以使用多個解析器,比如Python標準庫的parser,但是速度比較慢,也可以使用lxml作為解析器,但是它的使用方法、API跟lxml不太一樣。使用下來,還是lxml的API更舒服。

          lxml 對C語言庫 libxml2和 libxslt進行綁定,提供了Pythonic的API,它有一些主要特點:

          • 支持標準的XML
          • 支持(損壞)的HTML
          • 非常快的解析速度
          • Pythonic的API更易于使用
          • 使用Python的unicode字符串
          • 內存安全(沒有段錯誤)
          • 不需要手動管理內存

          總結為一句話就是,C語言的速度和Python的簡易相結合的神器。

          lxml有兩大部分,分別支持XML和HTML的解析:

          • lxml.etree 解析XML
          • lxml.html 解析html

          lxml.etree可以用來解析RSS feed,它就是一個XML格式的文檔。然而爬蟲抓取的絕大部分都是html網頁,所以,我們這里主要講述lxml.html解析網頁的方法。

          lxml.html 從html字符串生成文檔樹結構

          我們下載得到的網頁就是一串html字符串,如何把它輸入給lxml.html模塊,從而生成html文檔的樹結構呢?

          該模塊提供了幾種不同的方法:

          • parse(filename_url_or_file):
          • 輸入的是一個文件名、URL或文件對象(有read()方法)。
          • document_fromstring(string):
          • 輸入的是一個html的字符串,創建一個HTML文檔樹結構,它的根節點就是, 和 子節點。
          • fragment_fromstring(string, create_parent=False):
          • 返回輸入字符串的HTML片段。這個片段壁紙只含有一個element(元素),也就是單一節點,除非給出了create_parent 參數,否則會報錯。
          • fragments_fromstring(string):
          • 返回包含輸入字符串中所有片段的列表。
          • fromstring(string):
          • 返回值依據輸入字符串而定,如果輸入看起來像是一個文檔,則返回document_fromstring(string),如果是一個單一片段,則返回fragment_fromstring(string)。

          下面我們通過具體示例來說明上面幾個方法的不同。

          document_fromstring 的使用方法

          In [1]: import lxml.html as lh
          In [2]: z=lh.document_fromstring('<span>abc</span><span>xyz</span>')
          # 可以看到,它自動加了根節點<html>
          In [3]: z
          Out[3]: <Element html at 0x7fc410667b88>
          In [4]: z.tag
          Out[4]: 'html'
          # 還加了<body>節點
          In [5]: z.getchildren()
          Out[5]: [<Element body at 0x7fc4101a3ae8>]
          # 把字符串的兩個節點放在了<body>里面
          In [6]: z.getchildren()[0].getchildren()
          Out[6]: [<Element span at 0x7fc410092bd8>, <Element span at 0x7fc410667c28>]
          

          fragment_fromstring 的使用

          In [11]: z=lh.fragment_fromstring(‘<div>abc</div><div>xyz</div>’)
          ---------------------------------------------------------------------------
          ParserError Traceback (most recent call last)
          <ipython-input-11-a11f9a0f71d1> in <module>()
          ----> 1 z=lh.fragment_fromstring(‘<div>abc</div><div>xyz</div>’)
          ~/.virtualenvs/py3.6/lib/python3.6/site-packages/lxml/html/__init__.py in fragment_fromstring(html, create_parent, base_url, parser, **kw)
           850 raise etree.ParserError(
           851 “Multiple elements found (%s)”
          --> 852 % ‘, ‘.join([_element_name(e) for e in elements]))
           853 el=elements[0]
           854 if el.tail and el.tail.strip():
          ParserError: Multiple elements found (div, div)
          # 可以看到,輸入是兩個節點(element)時就會報錯
          # 如果加上 create_parent 參數,就沒問題了
          In [12]: z=lh.fragment_fromstring('<div>abc</div><div>xyz</div>', create_parent='p')
          In [13]: z.tag
          Out[13]: 'p'
          In [14]: z.getchildren()
          Out[14]: [<Element div at 0x7fc40a41a818>, <Element div at 0x7fc40a41aea8>]
          

          fragments_fromstring 的使用

          # 輸入字符串含有一個節點,則返回包含這一個節點的列表
          In [17]: lh.fragments_fromstring('<div>abc</div>')
          Out[17]: [<Element div at 0x7fc40a124ea8>]
          # 輸入字符串含有多個節點,則返回包含這多個節點的列表
          In [18]: lh.fragments_fromstring('<div>abc</div><div>xyz</div>')
          Out[18]: [<Element div at 0x7fc40a124b88>, <Element div at 0x7fc40a124f98>]
          

          fromstring 的使用

          In [27]: z=lh.fromstring('<div>abc</div><div>xyz</div>')
          In [28]: z
          Out[28]: <Element div at 0x7fc40a0eb368>
          In [29]: z.getchildren()
          Out[29]: [<Element div at 0x7fc410135548>, <Element div at 0x7fc40a0eb2c8>]
          In [30]: type(z)
          Out[30]: lxml.html.HtmlElement
          

          這里,fromstring輸入的如果是多個節點,它會給加一個父節點并返回。但是像html網頁都是從節點開始的,我們使用fromstring() 和 document_fromstring() 都可以得到完整的網頁結構。

          從上面代碼中我們可以看到,那幾個函數返回的都是HtmlElement對象,也就是說,我們已經學會了如何從html字符串得到HtmlElement的對象,下一節我們將學習如何操作HtmlElement對象,從中提取我們感興趣的數據。


          主站蜘蛛池模板: AA区一区二区三无码精片| 中文字幕在线看视频一区二区三区| 日韩精品一区二区三区老鸭窝| 无码精品久久一区二区三区 | 无码精品人妻一区二区三区免费看 | 中文精品一区二区三区四区| 无码少妇一区二区浪潮免费| 狠狠综合久久av一区二区| 婷婷国产成人精品一区二| 无码少妇丰满熟妇一区二区| 国产精品视频第一区二区三区| 鲁丝丝国产一区二区| 亚洲色无码专区一区| 久久综合亚洲色一区二区三区| 色视频综合无码一区二区三区| 亚洲综合激情五月色一区| 精品亚洲AV无码一区二区 | 爆乳无码AV一区二区三区| 国产成人无码一区二区在线观看| 日韩精品久久一区二区三区| 成人精品视频一区二区三区尤物| 国产一区二区三区在线看| 中文字幕一区二区三区日韩精品 | 五月婷婷一区二区| 91在线一区二区| 中文字幕AV无码一区二区三区| 亚洲视频一区二区三区| 亚洲一区二区三区高清在线观看| 国产麻豆精品一区二区三区v视界| 人妻少妇精品一区二区三区| 成人午夜视频精品一区| 一区二区三区电影在线观看| 中文字幕一区二区三| 99久久综合狠狠综合久久一区| 无码人妻视频一区二区三区| 国产精品视频第一区二区三区| 成人乱码一区二区三区av| 久久久综合亚洲色一区二区三区 | 国产一区二区三区精品视频| 亚洲一区二区三区日本久久九| 欧美日韩国产免费一区二区三区|