Python網絡爬蟲實戰(二)數據解析

  • 2019 年 10 月 3 日
  • 筆記

上一篇說完了如何爬取一個網頁,以及爬取中可能遇到的幾個問題。那麼接下來我們就需要對已經爬取下來的網頁進行解析,從中提取出我們想要的數據。

根據爬取下來的數據,我們需要寫不同的解析方式,最常見的一般都是HTML數據,也就是網頁的源碼,還有一些可能是Json數據,Json數據是一種輕量級的數據交換格式,相對來說容易解析,它的格式如下。

{      "name": "中國",      "province": [{          "name": "黑龍江",          "cities": {              "city": ["哈爾濱", "大慶"]          }      }, {          "name": "廣東",          "cities": {              "city": ["廣州", "深圳", "珠海"]          }      }, {          "name": "台灣",          "cities": {              "city": ["台北", "高雄"]          }      }, {          "name": "新疆",          "cities": {              "city": ["烏魯木齊"]          }      }]  }

上一篇說到的爬取攜程加載不出來的那部分數據就是異步請求Json返回給我們的,對於這類數據,Python有着十分便捷的解析庫,所以我們相對不用寫多少代碼。

但是對於爬取下來是一個HTML數據,其中標籤結構可能十分複雜,而且不同HTML的結構可能存在差異,所以解析方式也需要看情況而定。

相對方便的解析方式有正則表達式,xPath和BeautifulSoup4庫。

三者的運行速度相比當然是正則表達式最快,xPath其次,Bs4最慢了,因為Bs4是經過封裝的庫,相對於另外兩個,無疑是重裝坦克一般,但Bs4確實使用最簡單的一個,而正則表達式是最麻煩的一個。

正則表達式幾乎所有編程語言都支持,每一種語言的正則表達式都存在一點差異但大同小異。如果你是在設計一個複雜系統,就不要考慮正則表達式了,因為這種方法太過於不穩定,你永遠不敢保證你寫的正則規則是對應當前系統完全不會報錯的。

xPath 是一門在XML文檔中查找信息的語言。xPath可用來在XML文檔中對元素和屬性進行遍歷。

關於正則表達式和xPath在之後的實戰中再做詳解,現在主要是掌握Bs4的使用。

我們首先需要下載Bs4的庫。

pip install lxml  pip install beautifulsoup4

當我們爬取下來一整個網頁的HTML之後,Bs4就可以根據標籤的相對定位來找准你要爬取的數據了。

這個相對定位類似於如下:

body > div.banner > div > div.celeInfo-right.clearfix > div.movie-stats-container > div > div > span > span

可以理解把HTML頁面當做洋蔥一層一層剝開。

這種定位叫做selector,我們可以不用自己編寫它,比較HTML結構可能比較複雜,很容易寫錯。

我們可以打開瀏覽器的控制台(F12),然後Elements裏面找到我們想要爬取之後解析的內容,這時候你鼠標放上去的位置對應頁面內容會變成藍色讓你來對比,如下圖。

1

可以發現,這些dd標籤裏面就是當前頁面所有的電影信息了。哪吒之魔童降世你可以理解為dd-1,巨鱷風暴可以當做dd-2,以此類推。

然後你把鼠標放在dd標籤上右鍵,會有一個copy選項,裏面有一個selector,就是將它的selector複製下來。

下面分別是哪吒之魔童降世和巨鱷風暴的selector,可以發現,只有最後的dd:nth-child不同。

#app > div > div.movies-panel > div.movies-list > dl > dd:nth-child(1)    #app > div > div.movies-panel > div.movies-list > dl > dd:nth-child(2)

有了這個規律,我們就可以很容易的一次性解析那種列表型網頁了。

3

# -*- coding: utf-8 -*-  import os  import re  from bs4 import BeautifulSoup  import requests    # 請求頭設置  header = {      'Accept': '*/*;',      'Connection': 'keep-alive',      'Accept-Language': 'zh-CN,zh;q=0.9',      'Accept-Encoding': 'gzip, deflate, br',      'Host': 'maoyan.com',      'Referer': 'http://maoyan.com/',      'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'  }    data = requests.get('https://maoyan.com/films', headers=header)  soup = BeautifulSoup(data.text, 'lxml')  titles = soup.select('#app > div > div.movies-panel > div.movies-list > dl > dd ')    print(titles)

來仔細講解一下上面這些代碼。

request.get(url,headers)是昨天說過的了,headers就是請求頭信息,裏面包含了我們客戶端的信息以及請求方式是Get還是Post等。

返回的data就是響應了,你可以直接print這個數據,但是這個響應體裏面不止包含網頁的HTML,還有這次請求的相關數據,比如響應碼,200說明成功,404說明沒有找到資源等。

data.text就是從響應體中拿到網頁HTML代碼了。

BeautifulSoup就是我們的主要解析對象,lxml是相應的解析方式。

通過調用BeautifulSoup的select選擇器方法,來從之前傳入的HTML中獲取相應的標籤。

這麼一看其實Bs4還是很簡單的,但這只是Bs4的基礎應用了,對於我們普通解析一個網頁已經足夠用了,如果感興趣可以去深入去了解一下,不過這個這麼說也只是工具庫,如果你不嫌麻煩可以自己解析。

看完代碼,如果現在我要拿到這個頁面的電影名稱,這時候上面這個selector就不能用了,因為它不夠精確,它只到了’

‘,而我們要精確到電影名稱。

用這個selector。

1

#app > div > div.movies-panel > div.movies-list > dl > dd:nth-child(1) > div.channel-detail.movie-item-title > a

其它方式幾乎都大同小異了。

以上是HTML的解析,我們爬取的數據有時還會是Json數據,這類數據相對來說十分規則,我倒是很希望目標數據會是Json格式。

比如上篇中的攜程。

它的航班信息就是請求Json返回的。

4

Python中正則表達式的解析十分簡單,你把它當做字典數據類型就可以了。

最開始你獲得的Json是一串字符串,通過Python的Json.loads(jsonData)之後,返回的其實就是字典數據類型,直接操作就可以了。

5

import json    jsonData = '{          "name":"gzj",          "age":"23",          "sex":"man",          "mail":{              "gmail":"[email protected]",              "qmail":"[email protected]"              }          }'    res = json.loads(jsonData)    print(res['mail']['qmail'])

(最近在想實戰部分要不要錄視頻和文章兩部分,歡迎關注公眾號來康康!)