隨著科技不斷發(fā)展于样,互聯(lián)網(wǎng)已經(jīng)進(jìn)入了大數(shù)據(jù)時(shí)代疏叨。
我們過(guò)去只能通過(guò)報(bào)刊雜志、電視廣播獲取到有限的信息穿剖,而現(xiàn)在蚤蔓,互聯(lián)網(wǎng)上的海量數(shù)據(jù),讓我們享受到了信息自由糊余。
但是秀又,我們獲取到了海量的信息同時(shí),也帶來(lái)了大量的垃圾信息贬芥。
所以必須要通過(guò)一些技術(shù)手段進(jìn)行收集涮坐、整理、分析誓军、篩選,然后才能獲取到對(duì)我們有用的相關(guān)內(nèi)容疲扎。
而這個(gè)技術(shù)手段昵时,就叫網(wǎng)絡(luò)爬蟲(chóng)技術(shù)。
前兩天老鐵跟我吐槽椒丧,他的老板突然要他收集豆瓣電影Top250榜單上的電影詳細(xì)信息壹甥,然后做成Excel表格。
他當(dāng)時(shí)聽(tīng)到這個(gè)消息很崩潰壶熏,他的本職工作不是這一方面句柠,只是被臨時(shí)拉來(lái)頂班。他當(dāng)時(shí)跟我說(shuō)這么多的信息棒假,復(fù)制粘貼也需要很多時(shí)間溯职,在他花費(fèi)了一大把時(shí)間,但是并沒(méi)有什么成果帽哑。
所以他來(lái)問(wèn)我:你們程序員有沒(méi)有什么黑科技谜酒,可以快速收集網(wǎng)頁(yè)信息。
我當(dāng)時(shí)靈光一閃妻枕,這用Python爬蟲(chóng)技術(shù)不就可以很快實(shí)現(xiàn)僻族。用幾行代碼快速獲取信息,生成Excel表格屡谐。
爬蟲(chóng)案例講解
爬蟲(chóng)可以爬取的內(nèi)容有很多述么,比如房?jī)r(jià)、房源數(shù)據(jù)愕掏,股票信息或者是購(gòu)物網(wǎng)上的一些商品信息度秘,就是大部分網(wǎng)頁(yè)上有的信息都可以爬取下來(lái),尤其對(duì)于信息收集工作者來(lái)說(shuō)亭珍,簡(jiǎn)直是福音敷钾。
對(duì)于初學(xué)者來(lái)說(shuō)枝哄,復(fù)雜的爬蟲(chóng)案例可能會(huì)有困難,所以我教大家簡(jiǎn)單的網(wǎng)頁(yè)信息爬取阻荒,以豆瓣電影TOP250榜單為例挠锥,把電影信息爬取下來(lái)。話(huà)不多說(shuō)侨赡,往下看↓ ↓ ↓
這是爬取的結(jié)果:
我這邊用的是pychram 運(yùn)行的蓖租,最開(kāi)始就是導(dǎo)入庫(kù)和模塊
# -*- codeing = utf-8 -*-
from bs4 import BeautifulSoup # 網(wǎng)頁(yè)解析,獲取數(shù)據(jù)
import re # 正則表達(dá)式羊壹,進(jìn)行文字匹配
import urllib.request, urllib.error # 指定URL蓖宦,獲取網(wǎng)頁(yè)數(shù)據(jù)
import xlwt # 進(jìn)行excel操作
#import sqlite3 # 進(jìn)行SQLite數(shù)據(jù)庫(kù)操作
開(kāi)頭的這個(gè)是設(shè)置編碼為utf-8 ,寫(xiě)在開(kāi)頭油猫,防止亂碼稠茂。
本次爬蟲(chóng)能用到的就是這些庫(kù),后面也都加了注釋?zhuān)疫@里主要講存儲(chǔ)在Excel里情妖,也可以用數(shù)據(jù)庫(kù)操作睬关。
我們主要爬取的是
https://movie.douban.com/top250 這個(gè)網(wǎng)址,它跳轉(zhuǎn)的是以這個(gè)網(wǎng)頁(yè)毡证,我們主要是要爬取左側(cè)電影的信息电爹。
爬取網(wǎng)頁(yè)大致分三步
1.獲取數(shù)據(jù)
2.解析內(nèi)容
3.保存數(shù)據(jù)
(一)獲取數(shù)據(jù)
def main():
baseurl = "https://movie.douban.com/top250?start=" #要爬取的網(wǎng)頁(yè)鏈接
# 1.爬取網(wǎng)頁(yè)
datalist = getData(baseurl)
baseurl 就是我們要爬取的網(wǎng)頁(yè)鏈接,下面就是調(diào)用getData(baseurl)
# 爬取網(wǎng)頁(yè)
def getData(baseurl):
datalist = [] #用來(lái)存儲(chǔ)爬取的網(wǎng)頁(yè)信息
for i in range(0, 10): # 調(diào)用獲取頁(yè)面信息的函數(shù)料睛,10次
url = baseurl + str(i * 25)
html = askURL(url)
這里為什么要調(diào)用10次丐箩?因?yàn)槎拱觌娪癟op250,頁(yè)面包括250條電影數(shù)據(jù)恤煞,分10頁(yè)屎勘,每頁(yè)25條。每頁(yè)URL的不同之處:最后的頁(yè)面數(shù)值=(頁(yè)面數(shù)-1)25阱州,所以我們需要訪(fǎng)問(wèn)頁(yè)面10次挑秉,2510=250。
然后就請(qǐng)求網(wǎng)頁(yè)苔货,Python一般用urllib2庫(kù)獲取頁(yè)面
# 得到指定一個(gè)URL的網(wǎng)頁(yè)內(nèi)容
def askURL(url):
head = { # 模擬瀏覽器頭部信息犀概,向豆瓣服務(wù)器發(fā)送消息
"User-Agent": "Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 80.0.3987.122 Safari / 537.36"
}
# 用戶(hù)代理,表示告訴豆瓣服務(wù)器夜惭,我們是什么類(lèi)型的機(jī)器姻灶、瀏覽器(本質(zhì)上是告訴瀏覽器,我們可以接收什么水平的文件內(nèi)容)
request = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
except urllib.error.URLError as e:
if hasattr(e, "code"):
print(e.code)
if hasattr(e, "reason"):
print(e.reason)
return html
對(duì)每一個(gè)頁(yè)面诈茧,調(diào)用askURL函數(shù)獲取頁(yè)面內(nèi)容产喉。
定義一個(gè)獲取頁(yè)面的函數(shù)askURL, 傳入一個(gè)urI參數(shù),表示網(wǎng)址曾沈,如https:/ /movie.douban.com/ top250?start=0这嚣。
urllib2.Request生成請(qǐng)求;;urllib2.urlopen發(fā)送請(qǐng)求獲取響應(yīng)塞俱; read 獲取頁(yè)面內(nèi)容姐帚。
在訪(fǎng)問(wèn)頁(yè)面時(shí)經(jīng)常會(huì)出現(xiàn)錯(cuò)誤,為了程序正常運(yùn)行障涯,加入異常捕獲try...except...語(yǔ)句罐旗。不然可能會(huì)出現(xiàn)這樣的錯(cuò)誤代碼↓
418 I’m a teapotThe HTTP 418 I’m a teapot client error response code indicates that
the server refuses to brew coffee because it is a teapot. This error
is a reference to Hyper Text Coffee Pot Control Protocol which was an
April Fools’ joke in 1998.
翻譯為:HTTP 418 I‘m a teapot客戶(hù)端錯(cuò)誤響應(yīng)代碼表示服務(wù)器拒絕煮咖啡,因?yàn)樗且粋€(gè)茶壺唯蝶。這個(gè)錯(cuò)誤是對(duì)1998年愚人節(jié)玩笑的超文本咖啡壺控制協(xié)議的引用九秀。
其實(shí)就是被網(wǎng)站認(rèn)出來(lái)是爬蟲(chóng),所以需要掩飾一下
(二)解析內(nèi)容
接下來(lái)就是逐一解釋數(shù)據(jù)
# 2.逐一解析數(shù)據(jù)
soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all('div', class_="item"): # 查找符合要求的字符串
data = [] # 保存一部電影所有信息
item = str(item)
link = re.findall(findLink, item)[0] # 通過(guò)正則表達(dá)式查找
主要是通正則表達(dá)式查找粘我。
正則表達(dá)式
正則表達(dá)式,通常被用來(lái)檢索鼓蜒、替換那些符合某個(gè)模式(規(guī)則)的文本。
正則表達(dá)式是對(duì)字符串操作的一種邏輯公式,就是用事先定義好的一-些特定字符及這些特定字符的組合,組成一個(gè)"規(guī)則字符串”, 這個(gè)"規(guī)則字符串”用來(lái)表達(dá)對(duì)字符串的一種過(guò)濾邏輯征字。Python中使用re模塊操作正則表達(dá)式友酱。
#影片詳情連接的規(guī)則
findLink = re.compile(r'<a href="(.*?)">') # 創(chuàng)建正則表達(dá)式對(duì)象,影片詳情鏈接的規(guī)則
#影片圖片
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S) #re.S 讓換行符包含在字符中
#影片片名
findTitle = re.compile(r'<span class="title">(.*)</span>')
#影片評(píng)分
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
#評(píng)價(jià)人數(shù)
findJudge = re.compile(r'<span>(\d*)人評(píng)價(jià)</span>')
#一句話(huà)簡(jiǎn)介
findInq = re.compile(r'<span class="inq">(.*)</span>')
#影片相關(guān)內(nèi)容
findBd = re.compile(r'<p class="">(.*?)</p>', re.S)
然后應(yīng)用規(guī)則找到我們所需要的內(nèi)容
#影片詳情連接
link = re.findall(findLink, item)[0] # re庫(kù)用來(lái)通過(guò)正則表達(dá)式查找指定的字符串
data.append(link) #添加鏈接
imgSrc = re.findall(findImgSrc, item)[0]
data.append(imgSrc) #添加圖片
titles = re.findall(findTitle, item) #片名可能只有中文名沒(méi)有外文名
if (len(titles) == 2):
ctitle = titles[0] #添加中文名
data.append(ctitle)
otitle = titles[1].replace("/", "") #去掉無(wú)關(guān)字符
data.append(otitle) #添加外文名
else:
data.append(titles[0])
data.append(' ') #如果沒(méi)有外文名就留空
rating = re.findall(findRating, item)[0]
data.append(rating) #添加評(píng)分
judgeNum = re.findall(findJudge, item)[0]
data.append(judgeNum) #添加評(píng)分人數(shù)
inq = re.findall(findInq, item)
if len(inq) != 0:
inq = inq[0].replace("柔纵。", "") #去掉句號(hào)
data.append(inq) #添加一句話(huà)簡(jiǎn)介
else:
data.append(" ")
bd = re.findall(findBd, item)[0] #電影詳細(xì)信息
bd = re.sub('<br(\s+)?/>(\s+)?', "", bd) #去掉<br/>
# bd = re.sub('/', "", bd)
data.append(bd.strip()) #去掉空格
datalist.append(data) #把處理好的電影信息放入datalist
return datalist
(三)保存數(shù)據(jù)
最后就是將獲取到的內(nèi)容保存到Excel里面
# 保存數(shù)據(jù)到表格
def saveData(datalist,savepath):
print("save.......")
book = xlwt.Workbook(encoding="utf-8",style_compression=0) #創(chuàng)建workbook對(duì)象
sheet = book.add_sheet('豆瓣電影Top250', cell_overwrite_ok=True) #創(chuàng)建工作表
col = ("電影詳情鏈接","海報(bào)圖片鏈接","影片中文名","影片外文名","豆瓣評(píng)分","評(píng)價(jià)人數(shù)","一句話(huà)簡(jiǎn)介","詳細(xì)信息")
for i in range(0,8):
sheet.write(0,i,col[i]) #列名
for i in range(0,250):
# print("第%d條" %(i+1)) #輸出語(yǔ)句,用來(lái)測(cè)試
data = datalist[i]
for j in range(0,8):
sheet.write(i+1,j,data[j]) #數(shù)據(jù)
book.save(savepath) #保存
最后運(yùn)行之后在左側(cè)會(huì)出現(xiàn)一個(gè)這樣的文件:
打開(kāi)可以看到就是我們獲取到的結(jié)果:
得到我們想要的結(jié)果后锤躁,稍微調(diào)整以下就可以交給領(lǐng)導(dǎo)了搁料,詳細(xì)又清晰。我教給老鐵這種方法后(從來(lái)沒(méi)有接觸過(guò)代碼的老鐵都學(xué)會(huì)了)系羞,他都開(kāi)心瘋了~
最后附上我所有的源代碼
# -*- codeing = utf-8 -*-
from bs4 import BeautifulSoup # 網(wǎng)頁(yè)解析郭计,獲取數(shù)據(jù)
import re # 正則表達(dá)式,進(jìn)行文字匹配
import urllib.request, urllib.error # 指定URL椒振,獲取網(wǎng)頁(yè)數(shù)據(jù)
import xlwt # 進(jìn)行excel操作
#影片詳情連接的規(guī)則
findLink = re.compile(r'<a href="(.*?)">') # 創(chuàng)建正則表達(dá)式對(duì)象昭伸,影片詳情鏈接的規(guī)則
#影片圖片
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S) #re.S 讓換行符包含在字符中
#影片片名
findTitle = re.compile(r'<span class="title">(.*)</span>')
#影片評(píng)分
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
#評(píng)價(jià)人數(shù)
findJudge = re.compile(r'<span>(\d*)人評(píng)價(jià)</span>')
#一句話(huà)簡(jiǎn)介
findInq = re.compile(r'<span class="inq">(.*)</span>')
#影片相關(guān)內(nèi)容
findBd = re.compile(r'<p class="">(.*?)</p>', re.S)
def main():
baseurl = "https://movie.douban.com/top250?start=" #要爬取的網(wǎng)頁(yè)鏈接
# 1.爬取網(wǎng)頁(yè)
datalist = getData(baseurl)
savepath = "豆瓣電影Top250.xls" #當(dāng)前目錄新建XLS,存儲(chǔ)進(jìn)去
# 3.保存數(shù)據(jù)
#saveData(datalist,savepath)
# 爬取網(wǎng)頁(yè)
def getData(baseurl):
datalist = [] #用來(lái)存儲(chǔ)爬取的網(wǎng)頁(yè)信息
for i in range(0, 10): # 調(diào)用獲取頁(yè)面信息的函數(shù)澎迎,10次
url = baseurl + str(i * 25)
html = askURL(url) # 保存獲取到的網(wǎng)頁(yè)源碼
# 2.逐一解析數(shù)據(jù)
soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all('div', class_="item"): # 查找符合要求的字符串庐杨,形成列表
data = [] # 保存一部電影所有信息
item = str(item)
#影片詳情連接
link = re.findall(findLink, item)[0] # re庫(kù)用來(lái)通過(guò)正則表達(dá)式查找指定的字符串
data.append(link) #添加鏈接
imgSrc = re.findall(findImgSrc, item)[0]
data.append(imgSrc) #添加圖片
titles = re.findall(findTitle, item) #片名可能只有中文名沒(méi)有外文名
if (len(titles) == 2):
ctitle = titles[0] #添加中文名
data.append(ctitle)
otitle = titles[1].replace("/", "") #去掉無(wú)關(guān)字符
data.append(otitle) #添加外文名
else:
data.append(titles[0])
data.append(' ') #如果沒(méi)有外文名就留空
rating = re.findall(findRating, item)[0]
data.append(rating) #添加評(píng)分
judgeNum = re.findall(findJudge, item)[0]
data.append(judgeNum) #添加評(píng)分人數(shù)
inq = re.findall(findInq, item)
if len(inq) != 0:
inq = inq[0].replace("。", "") #去掉句號(hào)
data.append(inq) #添加一句話(huà)簡(jiǎn)介
else:
data.append(" ")
bd = re.findall(findBd, item)[0] #電影詳細(xì)信息
bd = re.sub('<br(\s+)?/>(\s+)?', "", bd) #去掉<br/>
# bd = re.sub('/', "", bd)
data.append(bd.strip()) #去掉空格
datalist.append(data) #把處理好的電影信息放入datalist
return datalist
# 得到指定一個(gè)URL的網(wǎng)頁(yè)內(nèi)容
def askURL(url):
head = { # 模擬瀏覽器頭部信息夹供,向豆瓣服務(wù)器發(fā)送消息
"User-Agent": "Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 80.0.3987.122 Safari / 537.36"
}
# 用戶(hù)代理灵份,表示告訴豆瓣服務(wù)器,我們是什么類(lèi)型的機(jī)器哮洽、瀏覽器(本質(zhì)上是告訴瀏覽器填渠,我們可以接收什么水平的文件內(nèi)容)
request = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
except urllib.error.URLError as e:
if hasattr(e, "code"):
print(e.code)
if hasattr(e, "reason"):
print(e.reason)
return html
# 保存數(shù)據(jù)到表格
def saveData(datalist,savepath):
print("save.......")
book = xlwt.Workbook(encoding="utf-8",style_compression=0) #創(chuàng)建workbook對(duì)象
sheet = book.add_sheet('豆瓣電影Top250', cell_overwrite_ok=True) #創(chuàng)建工作表
col = ("電影詳情鏈接","圖片鏈接","影片中文名","影片外國(guó)名","評(píng)分","評(píng)價(jià)數(shù)","概況","相關(guān)信息")
for i in range(0,8):
sheet.write(0,i,col[i]) #列名
for i in range(0,250):
# print("第%d條" %(i+1)) #輸出語(yǔ)句,用來(lái)測(cè)試
data = datalist[i]
for j in range(0,8):
sheet.write(i+1,j,data[j]) #數(shù)據(jù)
book.save(savepath) #保存
if __name__ == "__main__": # 當(dāng)程序執(zhí)行時(shí)
# 調(diào)用函數(shù)
main()
print("爬取完畢!")
這樣我們的爬蟲(chóng)就爬取完畢了氛什,我這里只是以豆瓣榜單為例莺葫,這個(gè)方法對(duì)于爬取其他網(wǎng)頁(yè)也同樣適用。這樣做信息收集是特別方便枪眉,會(huì)大大提高工作效率捺檬。
有問(wèn)題的,不懂的可以在評(píng)論區(qū)提出瑰谜,或者私信我欺冀,看到就會(huì)回復(fù)。
最后關(guān)于兩種存儲(chǔ)方式:存儲(chǔ)到Excel和存儲(chǔ)到sqlite數(shù)據(jù)庫(kù)萨脑,兩種存儲(chǔ)方式可以選擇一種隐轩。我這里寫(xiě)的是存儲(chǔ)數(shù)據(jù)到Excel的,如果需要存儲(chǔ)數(shù)據(jù)庫(kù)源代碼的可以私信我渤早!