
一.前言
python作為一個解釋型語言,在資料分析,資料爬取方面有自己的先天優勢,近幾年也正被越來越多的人所使用,本篇文章以一個簡單的資料爬取的例子來幫助大家入門python,相信你會感興趣.同時對于喜歡看電影的小夥伴也是一個福利.
首先看一下成果,這是我們要爬取的頁面:
這樣的頁面總共有十頁,每一頁是25個,我們爬取每個電影的名稱,連結,評分等等資訊存儲在excel中,爬取效果如下:
二.總體思路
1.通過url請求,得到對應的html頁面;
2.通過BeautifulSoup取出與電影資訊相關的html代碼,然後通過正規表達式取 出具體的資料
3.将資料存儲至excel表格中.
第一步,擷取html代碼
我們需要模仿浏覽器向伺服器發送一個url請求,這樣就能得到伺服器的響應,也就是目前頁面的html代碼,通過以下代碼就可以.
# 請求頭中的User-Agent是直接copy浏覽器中的,顯示了浏覽器的型号,進而讓伺服器認為我們是一個浏覽器
header = {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"}
html=""
request=urllib.request.Request("https://movie.douban.com/top250?start=",headers=header) #構造請求資料
response = urllib.request.urlopen(request) #發起url請求
html=response.read().decode('utf-8') #用utf-8進行解碼
這樣我們就得到了伺服器響應的html代碼,如下:
因為整個html頁面代碼很多,這裡隻是截取了其中一部分,得到的html代碼應是與直接在浏覽器頁面右鍵單擊–>檢查,得到的源代碼一樣的,如下:
補充:其實模仿浏覽器發送url請求本身并不複雜,浏覽器向伺服器發送請求,本質上就是向伺服器發送了這些資料而已.那我們利用代碼也當然可以做到.
第二步,篩選具體資料
我們想要的資料就在這些html代碼中,那我們要篩選出我們想要的資料,這裡首先要利用一個工具類BeautifulSoup,通過浏覽器頁面選取元素我們可以知道,我們想要的資料在一個class='item’的div中
于是借助BeautifulSoup,使用如下代碼即可篩選出與每一個電影資料相關的html代碼.
bs = BeautifulSoup(html,"html.parser") #構造 BeautifulSoup類對象
items=bs.find_all('div',class_='item'): #該方法會比對出所有的符合内容,傳回一個集合
篩選出的結果如下(其中一個電影的資料):
<div class="item">
<div class="pic">
<em class="">1</em>
<a href="https://movie.douban.com/subject/1292052/">
<img width="100" alt="肖申克的救贖" src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
</a>
</div>
<div class="info">
<div class="hd">
<a href="https://movie.douban.com/subject/1292052/" class="">
<span class="title">肖申克的救贖</span>
<span class="title"> / The Shawshank Redemption</span>
<span class="other"> / 月黑高飛(港) / 刺激1995(台)</span>
</a>
<span class="playable">[可播放]</span>
</div>
<div class="bd">
<p class="">
導演: 弗蘭克·德拉邦特 Frank Darabont 主演: 蒂姆·羅賓斯 Tim Robbins /...<br>
1994 / 美國 / 犯罪 劇情
</p>
<div class="star">
<span class="rating5-t"></span>
<span class="rating_num" property="v:average">9.7</span>
<span property="v:best" content="10.0"></span>
<span>2075016人評價</span>
</div>
<p class="quote">
<span class="inq">希望讓人自由。</span>
</p>
</div>
</div>
</div>
再之後我們還需要篩選出具體的我們想要的資料,比如說電影名稱,評價等等資訊,這裡使用正規表達式進行篩選,在python需要借助re工具類來使用正則.
比如現在我們要篩選電影名稱,它在這一句代碼中.
<span class="title">肖申克的救贖</span>
,那我們可以這樣寫,
# ()作為一組,一個整體,比對出來的就是()裡面的内容
name=re.compile(r'<span class="title">(.*)</span>')
#findall方法就是進行比對,找出所有的符合的内容,該方法會傳回一個數組,是以要取第一個
name.findall(item)[0] #item就是使用BeautifulSoup已經篩選出的與電影相關的html代碼.也就是上一張代碼的内容.
其他評價,電影連結等等資訊和篩選電影名稱的代碼,思想是相似的,這裡不再贅述.
第三步,存儲資料.
我們需要将篩選出的資料存儲到excel中,這裡要用到xlwt工具類,将資料寫入到excel表格中.其實也就是調用對應的方法即可,那怎樣具體指定我們寫入到哪一個單元格當中呢?
這裡是将整個表格看作一個坐标軸,左上角為原點,坐标為(0,0).那麼下圖中所框住的表格的坐标就是(1,2).
現在舉例,我們想要在(0,0)單元格寫入hello資料,代碼可以這樣寫;
#建構一個workbook檔案對象,也就是excel檔案對象
workbook= xlwt.Workbook(encoding='utf-8')
#建立工作表對象,也就是worksheet,
sheet = workbook.add_sheet('sheet1')
#寫入資料,第一個是橫坐标,第二個是縱坐标,第三個是寫入的内容
sheet.write(0,0,'hello')
#儲存資料,不儲存的話是在記憶體中,參數就是檔案名稱
workbook.save('test.xls')
三.全部代碼
在實際操作中,我們需要循環處理,分别篩選出每一頁的資料存儲到一個總的數組中,然後将資料儲存,全部代碼如下:
from bs4 import BeautifulSoup #網頁解析,擷取資料
import re #正規表達式
import urllib.request,urllib.error #定制url,擷取網頁資料
import xlwt #進行excel操作
import sqlite3 #進行資料庫操作
def main():
# 擷取資料
baseurl="https://movie.douban.com/top250?start="
data=getDate(baseurl)
# 儲存資料
savePath=".\\豆瓣電影top250.xls" # .\就表示目前路徑
saveDate(savePath,data)
#得到指定一個url的網頁的内容
def askUrl(url):
# 請求頭中的User-Agent是直接copy浏覽器中的,顯示了浏覽器的型号,進而讓伺服器認為我們是一個浏覽器
header = {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"}
html=""
try:
request=urllib.request.Request(url,headers=header) #構造請求資料
response = urllib.request.urlopen(request) #發起url請求
html=response.read().decode('utf-8')
except urllib.error.URLError as e:
if hasattr(e,"code"): #如果有code屬性,列印出來
print(e.code)
if hasattr(e,"reason"): #如果有reason,列印出來
print(e.reason)
return html
#電影名稱
name=re.compile(r'<span class="title">(.*)</span>') # ()作為一組,一個整體,比對出來的就是()裡面的内容
#電影連結
link=re.compile(r'<a href="(.*)" target="_blank" rel="external nofollow" >')
#電影圖檔
img=re.compile(r'<img alt=".*src="(.*) width="100"/>')
#電影評分
mark=re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
#評分人數
markNum=re.compile(r'<span>(\d*)人評價</span>')
#電影關鍵詞
keyWords=re.compile(r'<span class="inq">(.*)</span>')
#電影詳情
details=re.compile(r'<p class="">(.*?)</p>',re.S)
#re.S是使.包括換行符,這裡必須包括?,就是0次到1次,不然會把其他包含進去.也就是當第一次遇到</p>時就結束,否則就會比對到最後一次遇到<\p>時結束.
def getDate(baseurl):
totaldata=[]
for i in range(0,10):
#擷取資料
html=askUrl(baseurl+str(i*25)) #循環調用分頁請求,每一頁25個資料
# 解析資料,大概思路就是通過bs找到大概的html代碼,然後通過re解析具體資料
bs = BeautifulSoup(html,"html.parser")
for item in bs.find_all('div',class_='item'):
data=[]
item=str(item)
data.append(name.findall(item)[0]) #添加電影名稱
data.append(link.findall(item)[0]) #添加電影連結
data.append(img.findall(item)[0]) #添加電影圖檔
data.append(mark.findall(item)[0]) #添加電影評分
data.append(markNum.findall(item)[0]) #添加電影評價人數
keyWord=keyWords.findall(item) #電影關鍵句有可能為空,要做處理
if len(keyWord) != 0:
keyWord=keyWord[0].replace('。','')
data.append(keyWord)
else:
data.append(' ')
detail=details.findall(item) #電影詳情需要去除空格,<div>等等多餘符号
detail=re.sub(r'<br(\s+)?/>(\s+)?','',detail[0]) #去除<br>,(\s+)? 表示比對任意空格,包括制表符,換行符等
detail=re.sub(r'/',',',detail)
data.append(detail.strip())
totaldata.append(data)
return totaldata
#儲存資料
def saveDate(savePath,data):
workbook= xlwt.Workbook(encoding='utf-8', style_compression=1)
sheet = workbook.add_sheet('豆瓣電影top250',cell_overwrite_ok=True) #cell_overwrite_ok表示每個單元格的是否可以被覆寫掉
cal=('電影名稱','電影連結','電影圖檔','電影評分','電影評價人數','電影關鍵句','電影詳情')
for i in range(0,7):
sheet.write(0,i,cal[i])
for index,i in enumerate(data):
print("儲存第{}行".format(index+1))
for j in range(0,7):
sheet.write(index+1,j,i[j])
workbook.save(savePath)
if __name__ == '__main__': # 程式的入口
main()
print("爬取完畢")
如果代碼中有什麼不了解的地方或者說覺得可以改進的地方,都可以評論哦,都會一一回應的.