今天學習了《python3網絡爬蟲開發實戰》的正規表達式部分,緊接着是一個爬蟲小項目:爬取貓眼電影排行,看着沒什麼難度,就想自己來獨立完成這個項目,部分參考了書上的代碼。
項目目标
利用正規表達式抓取貓眼電影TOP100電影資訊并儲存。
用到的庫
requests庫、re庫
初步分析
貓眼電影TOP100 的連結位址是
https://maoyan.com/board/4
,打開以後是這樣的:
把它拉到最下方,是有分頁的,點選第二頁:
我們可以看到頁面的URL變成了
https://maoyan.com/board/4?offset=10
,由此可以推測出改變offset就可以改變頁面顯示的電影(讀者可以自行在URL上任意修改數字),offset=n的時候,頁面顯示排名第n~n+10的電影,是以,我們通過改變offset的值可以抓取所有的頁面。
擷取單頁
首先要擷取到頁面,這裡使用requests庫。
import requests as req
def get_one_page(url):
#設定headers僞造浏覽器資訊
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"}
#擷取頁面
response = req.get(url, headers=headers)
#狀态碼200代表成功
if 200 == response.status_code:
return response.text
return None
構造分析器
首先我們要檢視網頁的源代碼(Ctrl+U):
可以看到:一部電影的資訊是夾在
<dd>....</dd>
标簽中間的,同理,我們可以找到電影的名稱、主演、上映時間等資訊。
接下來要構造函數來分析這個頁面,用到了re庫。
import re
def parse_one_page(html):
#找到所有的電影
films = re.findall('<dd>.*?</dd>', html, re.S)
films_info = []
for film in films:
film_info = {}
#利用正規表達式擷取電影的各種資訊
ranking = re.search('<i class="board-index.*?>(\d+)</i>', film, re.S)
name = re.search(' <p class="name">.*?title="(.*?)" .*?', film, re.S)
star = re.search('<p class="star">\s+(.*?)\s+</p>', film, re.S)
time = re.search('<p class="releasetime">(.*?)</p>', film, re.S)
film_info['ranking'] = ranking.group(1)
film_info['name'] = name.group(1)
film_info['star'] = star.group(1)
film_info['time'] = time.group(1)
films_info.append(film_info)
return films_info
到這裡,我們就已經把一頁的電影資訊找出來了。
爬取所有頁
接下來要把所有頁都爬下來:
def main():
link = 'https://maoyan.com/board/4?offset='
for i in range(0, 91, 10):
url = link+str(i)
html = get_one_page(url)
parse_one_page(html)
儲存結果
在這裡我寫了一個小函數來實作儲存的功能:
def save(content):
with open('maoyan.txt', 'a', encoding='utf-8') as f:
f.write(content)
然後我在
parse_one_page(html)
函數裡對每個電影資訊進行了儲存:
def parse_one_page(html):
films = re.findall('<dd>.*?</dd>', html, re.S)
films_info = []
for film in films:
film_info = {}
ranking = re.search('<i class="board-index.*?>(\d+)</i>', film, re.S)
name = re.search(' <p class="name">.*?title="(.*?)" .*?', film, re.S)
star = re.search('<p class="star">\s+(.*?)\s+</p>', film, re.S)
time = re.search('<p class="releasetime">(.*?)</p>', film, re.S)
film_info['ranking'] = ranking.group(1)
film_info['name'] = name.group(1)
film_info['star'] = star.group(1)
film_info['time'] = time.group(1)
films_info.append(film_info)
save(str(film_info)+'\n')
return films_info
結果展示
我最終的内容如圖所示:
代碼整合
整個項目所有代碼如下:
import requests as req
import re
def get_one_page(url):
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"}
response = req.get(url, headers=headers)
if 200 == response.status_code:
return response.text
return None
def parse_one_page(html):
films = re.findall('<dd>.*?</dd>', html, re.S)
films_info = []
for film in films:
film_info = {}
ranking = re.search('<i class="board-index.*?>(\d+)</i>', film, re.S)
name = re.search(' <p class="name">.*?title="(.*?)" .*?', film, re.S)
star = re.search('<p class="star">\s+(.*?)\s+</p>', film, re.S)
time = re.search('<p class="releasetime">(.*?)</p>', film, re.S)
film_info['ranking'] = ranking.group(1)
film_info['name'] = name.group(1)
film_info['star'] = star.group(1)
film_info['time'] = time.group(1)
films_info.append(film_info)
save(str(film_info)+'\n')
return films_info
def save(content):
with open('maoyan.txt', 'a', encoding='utf-8') as f:
f.write(content)
def main():
link = 'https://maoyan.com/board/4?offset='
for i in range(0, 91, 10):
url = link+str(i)
html = get_one_page(url)
parse_one_page(html)
if __name__ == '__main__':
main()
小結
這個項目是對靜态頁面的解析,相對簡單,适合入門,用正規表達式來解析頁面是一種比較不友善的方法,但也是一種必備技能,還可以用BeautifulSoup、Xpath等來進行頁面解析,更加靈活友善,功能也更加強大。為了簡便起見,本文的代碼還有很多不足之處,比如沒有設定休息時間,這在有一定反爬技術的網站上是行不通的;還比如沒有注意中文的編碼問題,有可能在其它網站上面爬下來的中文就是亂碼等等。
相關連結
《python3網絡爬蟲開發實戰》項目源碼