參考資料《Python3網(wǎng)絡(luò)爬蟲開發(fā)實踐》搀擂,作者崔慶才
這篇博客參考了崔慶才的《Python3網(wǎng)絡(luò)爬蟲開發(fā)實踐》有關(guān)部分,記錄了爬取貓眼電影網(wǎng)排名前100的電影信息的過程匈棘。
主要步驟有:
- 訪問網(wǎng)站厂捞,獲取頁面源碼
- 解析頁面睁本,得到想要的數(shù)據(jù)
- 循環(huán)爬取多個頁面
- 把數(shù)據(jù)寫入本地文件
1. 分析需要爬取的頁面結(jié)構(gòu)
訪問貓眼電影场靴。觀察頁面啡莉,會看到首頁上有排名前十的電影信息。
找到頁面中的分頁,點擊不同的頁碼票罐。對比不同頁面url的差別,會發(fā)現(xiàn)不同的分頁是以offset參數(shù)作為區(qū)分的泞边。
因為每個頁面都顯示10條電影信息该押,所以offset是以10作為偏移量的。所以第1頁的offset=0阵谚,第2頁的offset=10蚕礼,第3頁的offset=20,后面的頁面也是以此類推梢什。
2. 抓取首頁
2.1 獲取首頁的源碼
首先定義一個方法奠蹬,請求頁面,并獲得頁面源碼:
import requests
def get_one_page(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
def main():
url = 'http://maoyan.com/board/4'
html = get_one_page(url)
print(html)
main()
在打印結(jié)果中嗡午,可以看到頁面的源碼已經(jīng)返回囤躁。
獲取到的源碼中,有很多的信息不是我們需要的荔睹,這時候狸演,需要把有用的信息提取出來。
2.2 使用正則提取信息
使用谷歌瀏覽器的開發(fā)者工具查看頁面的源代碼僻他,可以發(fā)現(xiàn)我們需要的信息都包含在<dd>標(biāo)簽中宵距。
排名信息包含在class為board-index
的i標(biāo)簽中;
片名信息包含在class為name
的p標(biāo)簽內(nèi)的a標(biāo)簽中吨拗;
主演姓名包含在class為star
的p標(biāo)簽中满哪;
上映日期包含在class為releasetime
的p標(biāo)簽中;
評分分別包含在class為integer
和fraction
的i標(biāo)簽中劝篷;
電影封面圖在class為board-img
的img的src屬性中哨鸭;
因此,可以寫一個正則表達(dá)式來提取一個電影的上述信息:
<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>
把上面的正則表達(dá)式加入到代碼中:
import requests
import re
def get_one_page(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
def parse_one_page(html):
pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
+ '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
+ '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, html)
print(items)
def main():
url = 'http://maoyan.com/board/4'
html = get_one_page(url)
parse_one_page(html)
main()
輸出結(jié)果如下:
可以看到携龟,上面的輸出結(jié)果可讀性不是很好兔跌,把方法parse_one_page改進(jìn)如下:
def parse_one_page(html):
pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
+ '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
+ '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, html)
for item in items:
yield {
'index': item[0],
'image': item[1],
'title': item[2],
'actor': item[3].strip()[3:],
'time': item[4].strip()[5:],
'score': item[5] + item[6]
}
至此,單頁的電影信息已經(jīng)獲取完畢峡蟋。
接著將獲取到的信息保存到文本文件中坟桅,以供后續(xù)的使用。
2.3 寫入文件
使用JSON庫的dumps()方法實現(xiàn)字典的序列化蕊蝗,并指定ensure_ascii參數(shù)為false仅乓,這樣可以保證輸出結(jié)果是中文形式,整理代碼如下:
import requests
import re
import json
def get_one_page(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
def parse_one_page(html):
pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
+ '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
+ '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, html)
for item in items:
yield {
'index': item[0],
'image': item[1],
'title': item[2],
'actor': item[3].strip()[3:],
'time': item[4].strip()[5:],
'score': item[5] + item[6]
}
def write_to_file(content):
with open('top100.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(content, ensure_ascii=False)+'\n')
def main():
url = 'http://maoyan.com/board/4'
html = get_one_page(url)
for item in parse_one_page(html):
print(item)
write_to_file(item)
main()
這時候就會發(fā)現(xiàn)本地多了一個名為top100.txt的文件蓬戚,打開查看夸楣,里面存放了首頁排名前10的電影的各個信息。
接下來爬取另外頁面的電影信息。
3. 爬取其余頁面
爬取其余頁面豫喧,只需要對應(yīng)調(diào)整url的offset參數(shù)即可石洗,改寫main方法如下:
def main(offset):
url = 'http://maoyan.com/board/4?offset=' + str(offset)
html = get_one_page(url)
for item in parse_one_page(html):
print(item)
write_to_file(item)
if __name__ == '__main__':
for i in range(10):
main(offset=i*10)
time.sleep(1)
為了防止過快請求頁面,被封紧显,加入一個延時等待讲衫,最終代碼如下:
import json
import requests
from requests.exceptions import RequestException
import re
import time
def get_one_page(url):
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
def parse_one_page(html):
pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
+ '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
+ '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, html)
for item in items:
yield {
'index': item[0],
'image': item[1],
'title': item[2],
'actor': item[3].strip()[3:],
'time': item[4].strip()[5:],
'score': item[5] + item[6]
}
def write_to_file(content):
with open('top100.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(content, ensure_ascii=False) + '\n')
def main(offset):
url = 'http://maoyan.com/board/4?offset=' + str(offset)
html = get_one_page(url)
for item in parse_one_page(html):
print(item)
write_to_file(item)
if __name__ == '__main__':
for i in range(10):
main(offset=i * 10)
time.sleep(1)
查看top100.txt,會發(fā)現(xiàn)排名前100名的電影信息已經(jīng)整齊的寫入到了文件中孵班。
完涉兽。