python網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)
一、概述
網(wǎng)絡(luò)爬蟲(Web crawler),又稱為網(wǎng)絡(luò)蜘蛛(Web spider)或網(wǎng)絡(luò)機(jī)器人(Web robot),主要用來(lái)爬取目標(biāo)網(wǎng)站內(nèi)容的程序或腳本。
從功能上來(lái)區(qū)分網(wǎng)絡(luò)爬蟲:
- 數(shù)據(jù)采集
- 數(shù)據(jù)處理
- 數(shù)據(jù)儲(chǔ)存
以上三個(gè)部分,基本工作框架流程如下圖:

二、原理
功能:下載網(wǎng)頁(yè)數(shù)據(jù),為搜索引擎系統(tǒng)提供數(shù)據(jù)來(lái)源。組件:控制器、解析器、資源庫(kù)。
Web網(wǎng)絡(luò)爬蟲系統(tǒng)首先將種子URL放入下載隊(duì)列,然后簡(jiǎn)單地從隊(duì)首中取出一個(gè)URL下載其對(duì)應(yīng)的網(wǎng)頁(yè)。得到網(wǎng)頁(yè)的內(nèi)容將其儲(chǔ)存后,再經(jīng)過(guò)解析網(wǎng)頁(yè)中的鏈接信息可以得到一些新的URL,將這些URL加入下載隊(duì)列。然后取出一個(gè)URL,對(duì)其對(duì)應(yīng)的網(wǎng)頁(yè)進(jìn)行下載,再解析,如此反復(fù)進(jìn)行,直到遍歷了整個(gè)網(wǎng)絡(luò)或滿足某種條件后才會(huì)停止下來(lái)。
三、爬蟲分類
1、傳統(tǒng)爬蟲
傳統(tǒng)爬蟲從一個(gè)或若干初始網(wǎng)頁(yè)的URL開始,獲得初始網(wǎng)頁(yè)上的URL,在抓取網(wǎng)頁(yè)過(guò)程中,不斷從當(dāng)前頁(yè)面上抽取新的URL放入隊(duì)列,直到滿足系統(tǒng)的一定停止條件。
2、聚焦爬蟲
聚焦爬蟲工作流程較為復(fù)雜,需要根據(jù)一定的網(wǎng)頁(yè)分析算法過(guò)濾與主題無(wú)關(guān)的鏈接,保留有用鏈接并將其放入等待抓取URL隊(duì)列。然后它將根據(jù)一定搜索策略從隊(duì)列中選擇下一步要抓取的網(wǎng)頁(yè)URL,并重復(fù)上述過(guò)程,直到達(dá)到系統(tǒng)某一條件時(shí)停止。另外所有被爬蟲抓取的網(wǎng)頁(yè)將會(huì)被系統(tǒng)存儲(chǔ),進(jìn)行一定的分析、過(guò)濾,并建立索引,以便之后的查詢和檢索。對(duì)于聚焦爬蟲來(lái)說(shuō),這一過(guò)程所得到的分析結(jié)果還可能對(duì)以后的抓取過(guò)程給出反饋和指導(dǎo)。
3、通用網(wǎng)絡(luò)爬蟲(全網(wǎng)爬蟲)
通用網(wǎng)絡(luò)爬蟲又稱全網(wǎng)爬蟲, 爬行對(duì)象從一些種子URL擴(kuò)充到整個(gè)Web,主要為門戶站點(diǎn)搜索引擎和大型Web服務(wù)提供商采集數(shù)據(jù)。這類網(wǎng)絡(luò)爬蟲的爬行范圍和數(shù)量巨大,對(duì)于爬行速度和存儲(chǔ)空間要求較高,對(duì)于爬行頁(yè)面順序要求相對(duì)較低,同時(shí)由于待刷新頁(yè)面太多,通常采用并行工作方式,但需要較長(zhǎng)時(shí)間才能刷新一次頁(yè)面。雖然存在一定缺陷, 但通用網(wǎng)絡(luò)爬蟲適用于為搜索引擎搜索廣泛的主題,有較強(qiáng)應(yīng)用價(jià)值。
實(shí)際的網(wǎng)絡(luò)爬蟲系統(tǒng)通常是幾種爬蟲技術(shù)相結(jié)合實(shí)現(xiàn)的。
四、網(wǎng)頁(yè)抓取策略
在爬蟲系統(tǒng)中,待抓取URL隊(duì)列是很重要的一部分。隊(duì)列中URL以什么樣順序排列也是一個(gè)很重要的問(wèn)題,因?yàn)檫@涉及先抓取哪個(gè)頁(yè)面,后抓取哪個(gè)頁(yè)面。
而決定這些URL排列順序的方法,稱之為抓取策略。
1、寬度優(yōu)先搜索:
在抓取過(guò)程中,在完成當(dāng)前層次搜索后,才進(jìn)行下一層次搜索。
優(yōu)點(diǎn):算法設(shè)計(jì)和實(shí)現(xiàn)相對(duì)簡(jiǎn)單。缺點(diǎn):隨著抓取網(wǎng)頁(yè)增多,大量無(wú)關(guān)網(wǎng)頁(yè)將被下載并過(guò)濾,算法效率將變低。
2、深度優(yōu)先搜索:
從起始網(wǎng)頁(yè)開始,選擇一個(gè)URL進(jìn)入,分析這個(gè)網(wǎng)頁(yè)中的URL,一個(gè)鏈接一個(gè)鏈接地抓取下去,直到處理完一條路線之后再處理下一條URL中的路線。
例如,下圖中深度優(yōu)先搜索的遍歷方式時(shí) A 到 B 到 D 到 E 到 F(ABDECF),而寬度優(yōu)先搜索的遍歷方式是 A B C D E F 。

3、最佳優(yōu)先搜索:
按照一定的網(wǎng)頁(yè)分析法,預(yù)測(cè)候選URL與目標(biāo)網(wǎng)頁(yè)的相似度,或者與主題的相關(guān)性,并選取評(píng)價(jià)最好的一個(gè)或幾個(gè)URL進(jìn)行抓取。
4、反向鏈接數(shù)策略:
反向鏈接數(shù)是指一個(gè)網(wǎng)頁(yè)被其他網(wǎng)頁(yè)鏈接指向的數(shù)量。反向鏈接數(shù)表示的是一個(gè)網(wǎng)頁(yè)的內(nèi)容受到其他人的推薦程度。
5、Partial PageRank策略:
Partial PageRank算法借鑒了PageRank算法的思想,對(duì)于已經(jīng)下載的網(wǎng)頁(yè),連同待抓取URL隊(duì)列中的URL,形成網(wǎng)頁(yè)集合,計(jì)算每個(gè)頁(yè)面的PageRank值,計(jì)算完之后,將待抓取URL隊(duì)列中的URL按照PageRank值的大小排列,并按照該順序抓取頁(yè)面。
五、網(wǎng)頁(yè)抓取的方法
1、分布式爬蟲
用于目前互聯(lián)網(wǎng)中海量URL管理,它包含多個(gè)爬蟲(程序),每個(gè)爬蟲(程序)需要完成的任務(wù)和單個(gè)爬行器類似。它們從互聯(lián)網(wǎng)上下載網(wǎng)頁(yè),并把網(wǎng)頁(yè)保存在本地的磁盤,從中抽取URL并沿著這些URL的指向繼續(xù)爬行。由于并行爬行器需要分割下載任務(wù),可能爬蟲會(huì)將自己抽取的URL發(fā)送給其他爬蟲。
這些爬蟲可能分布在同一個(gè)局域網(wǎng)之中,或分散在不同地理位置。
現(xiàn)在比較流行的分布式爬蟲:
Apache Nutch: 依賴hadoop運(yùn)行,hadoop本身會(huì)消耗很多時(shí)間。Nutch是為搜索引擎設(shè)計(jì)的爬蟲,如果不是要做搜索引擎,盡量不要選擇Nutch。
2、Java爬蟲
用Java開發(fā)的抓取網(wǎng)絡(luò)資源的小程序,常用的工具包括Crawler4j、WebMagic、WebCollector等。
3、非Java爬蟲
Scrapy: 由Python編寫的,輕量級(jí)的、高層次的屏幕抓取框架。最吸引人的地方在于Scrapy是一個(gè)框架,任何使用者可以根據(jù)自己的需求進(jìn)行進(jìn)行修改,并具有一些高級(jí)函數(shù),可以簡(jiǎn)化抓取過(guò)程。
六、項(xiàng)目實(shí)戰(zhàn)
1、抓取指定網(wǎng)頁(yè)
抓取某網(wǎng)首頁(yè)
使用urllib模塊,此模塊提供了讀取Web頁(yè)面數(shù)據(jù)接口,可以像讀取本地文件一樣讀取www和ftp上的數(shù)據(jù)。urllib是一個(gè)URL處理包,這個(gè)包中集合了一些處理URL的模塊。
urllib.request 模塊: 用來(lái)打開和讀取URLs的。urllib.error 模塊: 包含一些由 urllib.request 產(chǎn)生的錯(cuò)誤,可以用try進(jìn)行捕捉處理。urllib.parse 模塊: 包含一些解析 URLs的方法。urllib.robotparser: 用來(lái)解析 robots.txt 文本文件。它提供了一個(gè)單獨(dú)的 RobotFileParser 類,通過(guò)該類提供的 can_fetch() 方法測(cè)試爬蟲是否可以下載一個(gè)頁(yè)面。
以下代碼為抓取某網(wǎng)頁(yè)的代碼:
import urllib.request
url = "https://www.douban.com/"
# 這邊需要模擬瀏覽器才能進(jìn)行抓取
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36'}
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request)
data = response.read()
# 這邊需要轉(zhuǎn)碼才能正常顯示
print(str(data, 'utf-8'))
# 下面代碼可以打印抓取網(wǎng)頁(yè)的各類信息
print(type(response))
print(response.geturl())
print(response.info())
print(response.getcode())
2、抓取包含關(guān)鍵詞網(wǎng)頁(yè)
代碼如下:
import urllib.request
data = {'word': '海賊王'}
url_values = urllib.parse.urlencode(data)
url = "http://www.baidu.com/s?"
full_url = url + url_values
data = urllib.request.urlopen(full_url).read()
print(str(data, 'utf-8'))
3、下載貼吧中圖片
代碼如下:
import re
import urllib.request
# 獲取網(wǎng)頁(yè)源代碼
def getHtml(url):
page = urllib.request.urlopen(url)
html = page.read()
return html
# 獲取網(wǎng)頁(yè)所有圖片
def getImg(html):
reg = r'src="([.*\S]*\.jpg)" pic_ext="jpeg"'
imgre = re.compile(reg)
imglist = re.findall(imgre, html)
return imglist
html = getHtml('https://tieba.baidu.com/p/3205263090')
html = html.decode('utf-8')
imgList = getImg(html)
imgName = 0
# 循環(huán)保存圖片
for imgPath in imgList:
f = open(str(imgName) + ".jpg", 'wb')
f.write((urllib.request.urlopen(imgPath)).read())
f.close()
imgName += 1
print('正在下載第 %s 張圖片 ' % imgName)
print('該網(wǎng)站圖片已經(jīng)下載完')
4、股票數(shù)據(jù)抓取
代碼如下:
import random
import re
import time
import urllib.request
# 抓取所需內(nèi)容
user_agent = ["Mozilla/5.0 (Windows NT 10.0; WOW64)", 'Mozilla/5.0 (Windows NT 6.3; WOW64)',
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36',
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; rv:11.0) like Gecko)',
'Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1',
'Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3',
'Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12',
'Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0',
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Win64; x64; Trident/4.0)',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)',
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E)',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Maxthon/4.0.6.2000 Chrome/26.0.1410.43 Safari/537.1 ',
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E; QQBrowser/7.3.9825.400)',
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0 ',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.92 Safari/537.1 LBBROWSER',
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; BIDUBrowser 2.x)',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/3.0 Safari/536.11']
stock_total = []
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36'}
for page in range(1, 8):
url = 'http://quote.stockstar.com/stock/ranklist_a_3_1_' + str(page) + '.html'
request = urllib.request.Request(url=url, headers={"User-Agent": random.choice(user_agent)})
response = urllib.request.urlopen(request)
content = str(response.read(), 'gbk')
pattern = re.compile('<tbody[\s\S]*</tbody')
body = re.findall(pattern, str(content))
pattern = re.compile('>(.*?)<')
# 正則匹配
stock_page = re.findall(pattern, body[0])
stock_total.extend(stock_page)
time.sleep(random.randrange(1, 4))
# 刪除空白字符
stock_last = stock_total[:]
print(' 代碼', '\t', ' 簡(jiǎn)稱', '\t', '最新價(jià)', '\t', '漲跌幅', '\t', '漲跌額', '\t', '5分鐘漲幅')
for i in range(0, len(stock_last), 13):
print(stock_last[i], '\t', stock_last[i + 1], '\t', stock_last[i + 2], '', '\t', stock_last[i + 3], '', '\t',
stock_last[i + 4], '\t', stock_last[i + 5])
六、結(jié)語(yǔ)
以上使用Python版本為 3.9。
本篇內(nèi)容參考自《Python3 數(shù)據(jù)分析與機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》一書,編寫此篇以學(xué)習(xí)為主。
寫完就有點(diǎn)懶洋洋的咩~(+ω+)

到此這篇關(guān)于python網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)的文章就介紹到這了,更多相關(guān)python 爬蟲內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非maisonbaluchon.cn所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。
關(guān)注官方微信