項(xiàng)目實(shí)戰(zhàn)
靜態(tài)網(wǎng)頁實(shí)戰(zhàn)
本節(jié)我們將為大家展現(xiàn)一個(gè)完整爬蟲的大致過程,此次項(xiàng)目?jī)?nèi)容為提取貓眼電影TOP100榜中的所有電影信息并存儲(chǔ)至CSV文件中,其首頁地址為 http://maoyan.com/board/4 ,在3.2.2中我們已經(jīng)獲取過第一頁中的所有電影名了,但是如何獲取第二頁、第三頁的數(shù)據(jù)呢,即獲取第二頁第三頁對(duì)應(yīng)的URL,那么我們可以在瀏覽器中不斷翻頁尋找地址欄中URL的變化規(guī)律:
<pre class="public-DraftStyleDefault-pre" data-offset-key="99sn9-0-0" style="box-sizing: inherit; margin: 1.4em 0px; padding: calc(0.888889em); font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<pre class="Editable-styled" data-block="true" data-editor="f0dsm" data-offset-key="99sn9-0-0" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">
第二頁: http://maoyan.com/board/4?offset=10
第三頁: http://maoyan.com/board/4?offset=20
第四頁: http://maoyan.com/board/4?offset=30
......
</pre>
</pre>
我們看見URL的改變規(guī)律就是參數(shù)offset值不斷偏移,每頁偏移的值為10,由此我們可以編寫一個(gè)獲取每頁數(shù)據(jù)函數(shù),接收參數(shù)就是頁碼數(shù):
<pre class="public-DraftStyleDefault-pre" data-offset-key="b5aka-0-0" style="box-sizing: inherit; margin: 1.4em 0px; padding: calc(0.888889em); font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<pre class="Editable-styled" data-block="true" data-editor="f0dsm" data-offset-key="b5aka-0-0" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
偏移參數(shù),默認(rèn)為0,即為第一頁
params = {
'offset': 0
}
def get_html(page):
'''
獲取一頁html頁面
:param page: 頁數(shù)
:return: 該頁html頁面
'''
params['offset'] = page * 10
url = ' http://maoyan.com/board/4'
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
html = response.text
return html
else:
return -1
except:
return None
</pre>
</pre>
當(dāng)我們獲取到html頁面后,就可以提取相應(yīng)的電影信息了,比如榜單張每一項(xiàng)電影都會(huì)有的屬性:電影名稱,主演,上映時(shí)間,評(píng)分等信息。提取信息有多種方式,下面我們利用正則表達(dá)式提取電影信息:
<pre class="public-DraftStyleDefault-pre" data-offset-key="2m0hr-0-0" style="box-sizing: inherit; margin: 1.4em 0px; padding: calc(0.888889em); font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<pre class="Editable-styled" data-block="true" data-editor="f0dsm" data-offset-key="2m0hr-0-0" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">
def parse_infor(html):
'''
提取html頁面中的電影信息
:param html: html頁面
:return: 電影信息列表
'''
編寫正則字符串規(guī)則,提取 電影名,主演,上映時(shí)間,評(píng)分信息
pat = re.compile('<div class="movie-item-info">. ?<p. ?><a. ?>(. ?)</a></p>. ?<p. ?>(. ?)</p>.?<p. ?>(. ?)</p>. ?</div>. ?<div. ?>. ?<p. ?><i. ?>(. ?)</i><i. ?>(. ?)</i></p>. ?</div>. ?</div>. ?</div>', re.S)
得到一個(gè)二重列表
results = re.findall(pat, html)
one_page_film = []
if results:
for result in results:
film_dict = {}
獲取電影名信息
film_dict['name'] = result[0]
獲取主演信息
start = result[1]
替換字符串中的 '\n' 字符,即換行字符
start.replace('\n', '')
去掉字符串兩邊的空格,并使用切片去除字符串開頭的'主演:'三個(gè)字符
start = start.strip()[3:]
film_dict['start'] = start
獲取上映時(shí)間信息
releasetime = result[2]
使用切片去除字符串開頭的'上映時(shí)間:'五個(gè)字符
releasetime = releasetime[5:]
film_dict['releasetime'] = releasetime
獲取評(píng)分信息,由于評(píng)分是有兩個(gè)字符拼接的,這里我們提取后也需要進(jìn)行拼接操作
left_half =result[3]
right_half = result[4]
score = left_half + right_half
film_dict['score'] = score
打印該電影信息:
print(film_dict)
將該電影信息字典存入一頁電影列表中
one_page_film.append(film_dict)
return one_page_film
else:
return None
</pre>
</pre>
不熟悉正則讀者要好好復(fù)習(xí)下前面的知識(shí),雖然正則寫起來可能會(huì)麻煩些,當(dāng)時(shí)他的提取效率是最高的,接下來我們就可以將提取好的電影信息進(jìn)行存儲(chǔ)操作,這里我們存儲(chǔ)為CSV文件:
<pre class="public-DraftStyleDefault-pre" data-offset-key="7cmg0-0-0" style="box-sizing: inherit; margin: 1.4em 0px; padding: calc(0.888889em); font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<pre class="Editable-styled" data-block="true" data-editor="f0dsm" data-offset-key="7cmg0-0-0" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">
def save_infor(one_page_film):
'''
存儲(chǔ)提取好的電影信息
:param html: 電影信息列表
:return: None
'''
with open('top_film.csv', 'a', newline='') as f:
csv_file = csv.writer(f)
for one in one_page_film:
csv_file.writerow([one['name'], one['start'], one['releasetime'], one['score']])
</pre>
</pre>
以上是獲取一頁html頁面并提取電影信息存儲(chǔ)至CSV中的過程,接下來我們構(gòu)造十頁的URL便可以完成貓眼電影TOP100榜中的所有電影信息的獲取和存儲(chǔ)了,以下是完整程序:
<pre class="public-DraftStyleDefault-pre" data-offset-key="ap1fk-0-0" style="box-sizing: inherit; margin: 1.4em 0px; padding: calc(0.888889em); font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<pre class="Editable-styled" data-block="true" data-editor="f0dsm" data-offset-key="ap1fk-0-0" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">
import requests
import re
import csv
import time
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
params = {
'offset': 0
}
def get_html(page):
'''
獲取一頁html頁面
:param page: 頁數(shù)
:return: 該頁html頁面
'''
params['offset'] = page * 10
url = ' http://maoyan.com/board/4'
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
html = response.text
return html
else:
return -1
except:
return None
def parse_infor(html):
'''
提取html頁面中的電影信息
:param html: html頁面
:return: 電影信息列表
'''
pat = re.compile('<div class="movie-item-info">. ?<p. ?><a. ?>(. ?)</a></p>. ?<p. ?>(. ?)</p>.?<p. ?>(. ?)</p>. ?</div>. ?<div. ?>. ?<p. ?><i. ?>(. ?)</i><i. ?>(. ?)</i></p>. ?</div>. ?</div>. ?</div>', re.S)
results = re.findall(pat, html)
one_page_film = []
if results:
for result in results:
film_dict = {}
獲取電影名信息
film_dict['name'] = result[0]
獲取主演信息
start = result[1]
替換字符串中的 '\n' 字符,即換行字符
start.replace('\n', '')
去掉字符串兩邊的空格,并使用切片去除字符串開頭的'主演:'三個(gè)字符
start = start.strip()[3:]
film_dict['start'] = start
獲取上映時(shí)間信息
releasetime = result[2]
使用切片去除字符串開頭的'上映時(shí)間:'五個(gè)字符
releasetime = releasetime[5:]
film_dict['releasetime'] = releasetime
獲取評(píng)分信息
left_half =result[3]
right_half = result[4]
score = left_half + right_half
film_dict['score'] = score
打印該電影信息:
print(film_dict)
將該電影信息字典存入一頁電影列表中
one_page_film.append(film_dict)
return one_page_film
else:
return None
def save_infor(one_page_film):
'''
存儲(chǔ)提取好的電影信息
:param one_page_film: 電影信息列表
:return: None
'''
with open('top_film.csv', 'a', newline='', errors='ignore') as f:
csv_file = csv.writer(f)
for one in one_page_film:
csv_file.writerow([one['name'], one['start'], one['releasetime'], one['score']])
if name == " main ":
利用循環(huán)構(gòu)建頁碼
for page in range(10):
請(qǐng)求頁面
html = get_html(page)
if html:
提取信息
one_page_film = parse_infor(html)
if one_page_film:
存儲(chǔ)信息
save_infor(one_page_film)
time.sleep(1)
</pre>
</pre>
動(dòng)態(tài)網(wǎng)頁實(shí)戰(zhàn)
本節(jié)我們將爬取貓眼電影實(shí)時(shí)票房數(shù)據(jù),學(xué)會(huì)在動(dòng)態(tài)網(wǎng)頁中獲取我們想要的數(shù)據(jù),首先打開貓眼專業(yè)版-實(shí)時(shí)票房, 其網(wǎng)址為: https://piaofang.maoyan.com/dashboard ,然后我們可以看見現(xiàn)在的實(shí)時(shí)電影票房數(shù)據(jù),可以看見 “今日實(shí)時(shí)” 的數(shù)據(jù)在不斷地動(dòng)態(tài)增加:

image
而當(dāng)我們查看該網(wǎng)頁源代碼時(shí),卻并沒有電影相關(guān)的票房等信息,那么可以判斷該頁面可能使用了Ajax(即“Asynchronous Javascript And XML”(異步 JavaScript 和 XML))技術(shù),即動(dòng)態(tài)網(wǎng)頁(是指跟靜態(tài)網(wǎng)頁相對(duì)的一種網(wǎng)頁編程技術(shù)。靜態(tài)網(wǎng)頁,隨著html代碼的生成,頁面的內(nèi)容和顯示效果就基本上不會(huì)發(fā)生變化了——除非你修改頁面代碼。而動(dòng)態(tài)網(wǎng)頁則不然,頁面代碼雖然沒有變,但是顯示的內(nèi)容卻是可以隨著時(shí)間、環(huán)境或者數(shù)據(jù)庫操作的結(jié)果而發(fā)生改變)。我們可以利用瀏覽器的開發(fā)者工具進(jìn)行分析:

image
我們可以發(fā)現(xiàn)每隔一段時(shí)間都會(huì)有一個(gè)新的請(qǐng)求,其請(qǐng)求類型都為xhr,而Ajax的請(qǐng)求類型就是xhr,這請(qǐng)求可能就是實(shí)時(shí)更新的票房信息,而我們需要的數(shù)據(jù)可能就在這些文件里,于是我們選擇一個(gè)進(jìn)行分析:

image
在Preview中,我們可以看見大量的電影相關(guān)的信息,即我們想要獲取的實(shí)時(shí)電影票房數(shù)據(jù),而這些內(nèi)容是JSON格式的,瀏覽器開發(fā)者工具自動(dòng)做了解析方便我們查看,接下來我們只需要用Python模擬這些Ajax請(qǐng)求,拿下這些數(shù)據(jù)然后解析即可,而這些Ajax無非依然是HTTP請(qǐng)求,所以只要拿到對(duì)應(yīng)URL然后使用Python模擬該請(qǐng)求即可,我們可以直接復(fù)制,如下圖:

image
獲取到該請(qǐng)求的鏈接,接下來我們就用Python模擬該請(qǐng)求:
<pre class="public-DraftStyleDefault-pre" data-offset-key="2jmdt-0-0" style="box-sizing: inherit; margin: 1.4em 0px; padding: calc(0.888889em); font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<pre class="Editable-styled" data-block="true" data-editor="f0dsm" data-offset-key="2jmdt-0-0" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
def get_html():
'''
獲取JSON文件
:return: JSON格式的數(shù)據(jù)
'''
請(qǐng)求second.json的URL
url = ' https://box.maoyan.com/promovie/api/box/second.json'
try:
response = requests.get(url, headers=headers)
if response.status_code == 200:
由于是JSON文件,我們可以返回JSON格式的數(shù)據(jù)便于后續(xù)提取
return response.json()
else:
return -1
except:
return None
</pre>
</pre>
獲取對(duì)應(yīng)的JSON數(shù)據(jù)后,我們就可以利用進(jìn)行提取操作了。
<pre class="public-DraftStyleDefault-pre" data-offset-key="1f72a-0-0" style="box-sizing: inherit; margin: 1.4em 0px; padding: calc(0.888889em); font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<pre class="Editable-styled" data-block="true" data-editor="f0dsm" data-offset-key="1f72a-0-0" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">
def parse_infor(json):
'''
從JSON數(shù)據(jù)中提取電影票房數(shù)據(jù),包括:電影名,上映信息,綜合票房,票房占比,累計(jì)票房
:param json: JSON格式的數(shù)據(jù)
:return: 每次循環(huán)返回一次字典類型的電影數(shù)據(jù)
'''
if json:
利用json中的get()方法層層獲取對(duì)應(yīng)的信息
items = json.get('data').get('list')
for item in items:
piaofang = {}
piaofang['電影名'] = item.get('movieName')
piaofang['上映信息'] = item.get('releaseInfo')
piaofang['綜合票房'] = item.get('boxInfo')
piaofang['票房占比'] = item.get('boxRate')
piaofang['累計(jì)票房'] = item.get('sumBoxInfo')
利用生成器每次循環(huán)都返回一個(gè)數(shù)據(jù)
yield piaofang
else:
return None
</pre>
</pre>
讀者可能看見我們沒有使用常規(guī)的return進(jìn)行函數(shù)返回,而是使用了生成器,這樣就能每次循環(huán)都返回一次數(shù)據(jù),具體讀者可以 生成器 | 廖雪峰的官方網(wǎng)站 進(jìn)一步了解學(xué)習(xí),接下來我們就將提取好的票房信息存儲(chǔ)為格式化的HTML文件:
<pre class="public-DraftStyleDefault-pre" data-offset-key="b5r5l-0-0" style="box-sizing: inherit; margin: 1.4em 0px; padding: calc(0.888889em); font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<pre class="Editable-styled" data-block="true" data-editor="f0dsm" data-offset-key="b5r5l-0-0" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">
def save_infor(results):
'''
存儲(chǔ)格式化的電影票房數(shù)據(jù)HTML文件
:param results: 電影票房數(shù)據(jù)的生成器
:return: None
'''
rows = ''
for piaofang in results:
利用Python中的format字符串填充html表格中的內(nèi)容
row = '<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>'.format(piaofang['電影名'],
piaofang['上映信息'],
piaofang['綜合票房'],
piaofang['票房占比'],
piaofang['累計(jì)票房'])
利用字符串拼接循環(huán)存儲(chǔ)每個(gè)格式化的電影票房信息
rows = rows + '\n' + row
利用字符串拼接處格式化的HTML頁面
piaofang_html = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>電影票房</title>
</head>
<body>
<style>
.table1_5 table {
width:100%;
margin:15px 0
}
.table1_5 th {
background-color:#00BFFF;
color:#FFFFFF
}
.table1_5,.table1_5 th,.table1_5 td
{
font-size:0.95em;
text-align:center;
padding:4px;
border:1px solid #dddddd;
border-collapse:collapse
}
.table1_5 tr:nth-child(odd){
background-color:#aae9fe;
}
.table1_5 tr:nth-child(even){
background-color:#fdfdfd;
}
</style>
<table class='table1_5'>
<tr>
<th>電影名</th>
<th>上映信息</th>
<th>綜合票房</th>
<th>票房占比</th>
<th>累計(jì)票房</th>
</tr>
''' + rows + '''
</table>
</body>
</html>
'''
存儲(chǔ)已經(jīng)格式化的html頁面
with open('piaofang.html', 'w', encoding='utf-8') as f:
f.write(piaofang_html)
</pre>
</pre>
我們將以上過程整合,即可得到完整的票房數(shù)據(jù)獲取的代碼實(shí)例:
<pre class="public-DraftStyleDefault-pre" data-offset-key="bd99b-0-0" style="box-sizing: inherit; margin: 1.4em 0px; padding: calc(0.888889em); font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<pre class="Editable-styled" data-block="true" data-editor="f0dsm" data-offset-key="bd99b-0-0" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 0.9em; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
def get_html():
'''
獲取JSON文件
:return: JSON格式的數(shù)據(jù)
'''
請(qǐng)求second.json的URL
url = ' https://box.maoyan.com/promovie/api/box/second.json'
try:
response = requests.get(url, headers=headers)
if response.status_code == 200:
由于是JSON文件,我們可以返回JSON格式的數(shù)據(jù)便于后續(xù)提取
return response.json()
else:
return -1
except:
return None
def parse_infor(json):
'''
從JSON數(shù)據(jù)中提取電影票房數(shù)據(jù),包括:電影名,上映信息,綜合票房,票房占比,累計(jì)票房
:param json: JSON格式的數(shù)據(jù)
:return: 每次循環(huán)返回一次字典類型的電影數(shù)據(jù)
'''
if json:
利用json中的get()方法層層獲取對(duì)應(yīng)的信息
items = json.get('data').get('list')
for item in items:
piaofang = {}
piaofang['電影名'] = item.get('movieName')
piaofang['上映信息'] = item.get('releaseInfo')
piaofang['綜合票房'] = item.get('boxInfo')
piaofang['票房占比'] = item.get('boxRate')
piaofang['累計(jì)票房'] = item.get('sumBoxInfo')
利用生成器每次循環(huán)都返回一個(gè)數(shù)據(jù)
yield piaofang
else:
return None
def save_infor(results):
'''
存儲(chǔ)格式化的電影票房數(shù)據(jù)HTML文件
:param results: 電影票房數(shù)據(jù)的生成器
:return: None
'''
rows = ''
for piaofang in results:
利用Python中的format字符串填充html表格中的內(nèi)容
row = '<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>'.format(piaofang['電影名'],
piaofang['上映信息'],
piaofang['綜合票房'],
piaofang['票房占比'],
piaofang['累計(jì)票房'])
利用字符串拼接循環(huán)存儲(chǔ)每個(gè)格式化的電影票房信息
rows = rows + '\n' + row
利用字符串拼接處格式化的HTML頁面
piaofang_html = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>電影票房</title>
</head>
<body>
<style>
.table1_5 table {
width:100%;
margin:15px 0
}
.table1_5 th {
background-color:#00BFFF;
color:#FFFFFF
}
.table1_5,.table1_5 th,.table1_5 td
{
font-size:0.95em;
text-align:center;
padding:4px;
border:1px solid #dddddd;
border-collapse:collapse
}
.table1_5 tr:nth-child(odd){
background-color:#aae9fe;
}
.table1_5 tr:nth-child(even){
background-color:#fdfdfd;
}
</style>
<table class='table1_5'>
<tr>
<th>電影名</th>
<th>上映信息</th>
<th>綜合票房</th>
<th>票房占比</th>
<th>累計(jì)票房</th>
</tr>
''' + rows + '''
</table>
</body>
</html>
'''
存儲(chǔ)已經(jīng)格式化的html頁面
with open('piaofang.html', 'w', encoding='utf-8') as f:
f.write(piaofang_html)
if name == " main ":
獲取信息
json = get_html()
提取信息
results = parse_infor(json)
存儲(chǔ)信息
save_infor(results)
</pre>
</pre>
HTML文件存儲(chǔ)效果如下圖所示:

image
可以看見,動(dòng)態(tài)網(wǎng)頁的爬蟲可能會(huì)更加簡(jiǎn)單些,關(guān)鍵就在于找到對(duì)應(yīng)的XHR格式的請(qǐng)求,而一般這種格式的文件都是JSON格式的,提取相對(duì)也會(huì)更加簡(jiǎn)單方便,而讀者可能會(huì)問為何要把這個(gè)信息存儲(chǔ)為HTML文件格式的呢,喜歡電影的讀者可能會(huì)經(jīng)常打開貓眼電影查看每天的電影票房數(shù)據(jù),何不嘗試將我們所學(xué)的爬蟲知識(shí)運(yùn)用起來制作一個(gè)定時(shí)爬取電影票房數(shù)據(jù)并推送至個(gè)人郵箱的爬蟲小程序呢,這樣就省得我們每天打開網(wǎng)頁查看,讓數(shù)據(jù)主動(dòng)為我們服務(wù),也算是學(xué)習(xí)致用了吧,感興趣的讀者可以自己嘗試下,下圖筆者根據(jù)這個(gè)爬蟲程序擴(kuò)展每天收到的實(shí)時(shí)票房信息郵件,每天定時(shí)爬取推送給筆者,列表內(nèi)容如下圖所示:

image
推動(dòng)內(nèi)容如下圖所示:

image
因?yàn)猷]箱定時(shí)推送會(huì)涉及郵箱設(shè)置、郵箱模塊使用和不同系統(tǒng)(Linux和Windows)定時(shí)任務(wù)的部署等諸多環(huán)節(jié),感覺會(huì)有些偏題,畢竟這是一篇爬蟲入門方面的文章