2020-12-12

Python爬蟲原理

一赵辕、爬蟲是什么?

如果我們把互聯(lián)網(wǎng)比作一張大的蜘蛛網(wǎng)啊研,數(shù)據(jù)便是存放于蜘蛛網(wǎng)的各個節(jié)點(diǎn),而爬蟲就是一只小蜘蛛,

沿著網(wǎng)絡(luò)抓取自己的獵物(數(shù)據(jù))爬蟲指的是:向網(wǎng)站發(fā)起請求恍飘,獲取資源后分析并提取有用數(shù)據(jù)的程序;

從技術(shù)層面來說就是通過程序模擬瀏覽器請求站點(diǎn)的行為谴垫,把站點(diǎn)返回的HTML代碼/JSON數(shù)據(jù)/二進(jìn)制數(shù)據(jù)(圖片章母、視頻) 爬到本地,進(jìn)而提取自己需要的數(shù)據(jù)翩剪,存放起來使用乳怎;


?



二、爬蟲的基本流程:


用戶獲取網(wǎng)絡(luò)數(shù)據(jù)的方式:

方式1:瀏覽器提交請求--->下載網(wǎng)頁代碼--->解析成頁面

方式2:模擬瀏覽器發(fā)送請求(獲取網(wǎng)頁代碼)->提取有用的數(shù)據(jù)->存放于數(shù)據(jù)庫或文件中

爬蟲要做的就是方式2前弯;


1蚪缀、發(fā)起請求

使用http庫向目標(biāo)站點(diǎn)發(fā)起請求,即發(fā)送一個Request

Request包含:請求頭恕出、請求體等?

Request模塊缺陷:不能執(zhí)行JS 和CSS 代碼


2询枚、獲取響應(yīng)內(nèi)容

如果服務(wù)器能正常響應(yīng),則會得到一個Response

Response包含:html浙巫,json金蜀,圖片刷后,視頻等


3、解析內(nèi)容

解析html數(shù)據(jù):正則表達(dá)式(RE模塊)渊抄,第三方解析庫如Beautifulsoup尝胆,pyquery等

解析json數(shù)據(jù):json模塊

解析二進(jìn)制數(shù)據(jù):以wb的方式寫入文件


4拟枚、保存數(shù)據(jù)

數(shù)據(jù)庫(MySQL鹉动,Mongdb、Redis)

文件



三姥闭、http協(xié)議 請求與響應(yīng)



Request:用戶將自己的信息通過瀏覽器(socket client)發(fā)送給服務(wù)器(socket server)

Response:服務(wù)器接收請求嘶炭,分析用戶發(fā)來的請求信息抱慌,然后返回?cái)?shù)據(jù)(返回的數(shù)據(jù)中可能包含其他鏈接,如:圖片眨猎,js抑进,css等)

ps:瀏覽器在接收Response后,會解析其內(nèi)容來顯示給用戶睡陪,而爬蟲程序在模擬瀏覽器發(fā)送請求然后接收Response后寺渗,是要提取其中的有用數(shù)據(jù)。



四兰迫、request

1信殊、請求方式:

常見的請求方式:GET / POST


2、請求的URL

url全球統(tǒng)一資源定位符汁果,用來定義互聯(lián)網(wǎng)上一個唯一的資源 例如:一張圖片涡拘、一個文件、一段視頻都可以用url唯一確定


url編碼

https://www.baidu.com/s?wd=圖片

圖片會被編碼(看示例代碼)


網(wǎng)頁的加載過程是:

加載一個網(wǎng)頁据德,通常都是先加載document文檔鳄乏,

在解析document文檔的時候,遇到鏈接棘利,則針對超鏈接發(fā)起下載圖片的請求


3橱野、請求頭

User-agent:請求頭中如果沒有user-agent客戶端配置,服務(wù)端可能將你當(dāng)做一個非法用戶host善玫;

cookies:cookie用來保存登錄信息

注意:一般做爬蟲都會加上請求頭







請求頭需要注意的參數(shù):

(1)Referrer:訪問源至哪里來(一些大型網(wǎng)站水援,會通過Referrer 做防盜鏈策略;所有爬蟲也要注意模擬)

(2)User-Agent:訪問的瀏覽器(要加上否則會被當(dāng)成爬蟲程序)

(3)cookie:請求頭注意攜帶


4茅郎、請求體

請求體

如果是get方式蜗元,請求體沒有內(nèi)容(get請求的請求體放在 url后面參數(shù)中,直接能看到)

如果是post方式系冗,請求體是format data


????ps:

????1奕扣、登錄窗口,文件上傳等毕谴,信息都會被附加到請求體內(nèi)

????2成畦、登錄,輸入錯誤的用戶名密碼涝开,然后提交循帐,就可以看到post,正確登錄后頁面通常會跳轉(zhuǎn)舀武,無法捕捉到post


五拄养、響應(yīng)Response

1、響應(yīng)狀態(tài)碼

  200:代表成功

  301:代表跳轉(zhuǎn)

  404:文件不存在

  403:無權(quán)限訪問

  502:服務(wù)器錯誤


2银舱、respone header

響應(yīng)頭需要注意的參數(shù):

(1)Set-Cookie:BDSVRTM=0; path=/:可能有多個瘪匿,是來告訴瀏覽器,把cookie保存下來

(2)Content-Location:服務(wù)端響應(yīng)頭中包含Location返回瀏覽器之后寻馏,瀏覽器就會重新訪問另一個頁面



3棋弥、preview就是網(wǎng)頁源代碼

JSO數(shù)據(jù)

如網(wǎng)頁html,圖片

二進(jìn)制數(shù)據(jù)等



六诚欠、總結(jié)

1顽染、總結(jié)爬蟲流程:

?爬取--->解析--->存儲


2、爬蟲所需工具:

?請求庫:requests,selenium(可以驅(qū)動瀏覽器解析渲染CSS和JS轰绵,但有性能劣勢(有用沒用的網(wǎng)頁都會加載)粉寞;)?解析庫:正則,beautifulsoup左腔,pyquery?存儲庫:文件唧垦,MySQL,Mongodb液样,Redis


3振亮、爬獲校花網(wǎng)

最后送給大家點(diǎn)福利吧

基礎(chǔ)版:

import reimport requests

respose=requests.get('http://www.xiaohuar.com/v/')# print(respose.status_code)# 響應(yīng)的狀態(tài)碼# print(respose.content)? #返回字節(jié)信息# print(respose.text)? #返回文本內(nèi)容urls=re.findall(r'class="items".*?href="(.*?)"',respose.text,re.S)#re.S 把文本信息轉(zhuǎn)換成1行匹配url=urls[5]

result=requests.get(url)

mp4_url=re.findall(r'id="media".*?src="(.*?)"',result.text,re.S)[0]

video=requests.get(mp4_url)

with open('D:\\a.mp4','wb') as f:

? ? f.write(video.content)


函數(shù)封裝版

import reimport requestsimport hashlibimport time# respose=requests.get('http://www.xiaohuar.com/v/')# # print(respose.status_code)# 響應(yīng)的狀態(tài)碼# # print(respose.content)? #返回字節(jié)信息# # print(respose.text)? #返回文本內(nèi)容# urls=re.findall(r'class="items".*?href="(.*?)"',respose.text,re.S)? #re.S 把文本信息轉(zhuǎn)換成1行匹配# url=urls[5]# result=requests.get(url)# mp4_url=re.findall(r'id="media".*?src="(.*?)"',result.text,re.S)[0]#

# video=requests.get(mp4_url)#

# with open('D:\\a.mp4','wb') as f:#? ? f.write(video.content)#def get_index(url):

? ? respose = requests.get(url)

? ? ifrespose.status_code==200:

? ? ? ? return respose.textdef parse_index(res):

? ? urls = re.findall(r'class="items".*?href="(.*?)"', res,re.S)# re.S 把文本信息轉(zhuǎn)換成1行匹配return urlsdef get_detail(urls):

? ? forurlin urls:

? ? ? ? ifnoturl.startswith('http'):

? ? ? ? ? ? url='http://www.xiaohuar.com%s'%url

? ? ? ? result = requests.get(url)

? ? ? ? ifresult.status_code==200 :

? ? ? ? ? ? mp4_url_list = re.findall(r'id="media".*?src="(.*?)"', result.text, re.S)

? ? ? ? ? ? if mp4_url_list:

? ? ? ? ? ? ? ? mp4_url=mp4_url_list[0]

? ? ? ? ? ? ? ? print(mp4_url)

? ? ? ? ? ? ? ? # save(mp4_url)def save(url):

? ? video = requests.get(url)

? ? ifvideo.status_code==200:

? ? ? ? m=hashlib.md5()

? ? ? ? m.updata(url.encode('utf-8'))

? ? ? ? m.updata(str(time.time()).encode('utf-8'))

? ? ? ? filename=r'%s.mp4'% m.hexdigest()

? ? ? ? filepath=r'D:\\%s'%filename

? ? ? ? with open(filepath, 'wb') as f:

? ? ? ? ? ? f.write(video.content)def main():

? ? foriinrange(5):

? ? ? ? res1 = get_index('http://www.xiaohuar.com/list-3-%s.html'% i )

? ? ? ? res2 = parse_index(res1)

? ? ? ? get_detail(res2)if__name__=='__main__':

? ? main()


并發(fā)版(如果一共需要爬30個視頻蓄愁,開30個線程去做双炕,花的時間就是 其中最慢那份的耗時時間)


import reimport requestsimport hashlibimport timefromconcurrent.futuresimport ThreadPoolExecutor

p=ThreadPoolExecutor(30)#創(chuàng)建1個程池中,容納線程個數(shù)為30個撮抓;def get_index(url):

? ? respose = requests.get(url)

? ? ifrespose.status_code==200:

? ? ? ? return respose.textdef parse_index(res):

? ? res=res.result()#進(jìn)程執(zhí)行完畢后妇斤,得到1個對象urls = re.findall(r'class="items".*?href="(.*?)"', res,re.S)# re.S 把文本信息轉(zhuǎn)換成1行匹配forurlin urls:

? ? ? ? p.submit(get_detail(url))? #獲取詳情頁 提交到線程池defget_detail(url):#只下載1個視頻ifnoturl.startswith('http'):

? ? ? ? ? ? url='http://www.xiaohuar.com%s'%url

? ? ? ? result = requests.get(url)

? ? ? ? ifresult.status_code==200 :

? ? ? ? ? ? mp4_url_list = re.findall(r'id="media".*?src="(.*?)"', result.text, re.S)

? ? ? ? ? ? if mp4_url_list:

? ? ? ? ? ? ? ? mp4_url=mp4_url_list[0]

? ? ? ? ? ? ? ? print(mp4_url)

? ? ? ? ? ? ? ? # save(mp4_url)def save(url):

? ? video = requests.get(url)

? ? ifvideo.status_code==200:

? ? ? ? m=hashlib.md5()

? ? ? ? m.updata(url.encode('utf-8'))

? ? ? ? m.updata(str(time.time()).encode('utf-8'))

? ? ? ? filename=r'%s.mp4'% m.hexdigest()

? ? ? ? filepath=r'D:\\%s'%filename

? ? ? ? with open(filepath, 'wb') as f:

? ? ? ? ? ? f.write(video.content)def main():

? ? foriinrange(5):

? ? ? ? p.submit(get_index,'http://www.xiaohuar.com/list-3-%s.html'% i ).add_done_callback(parse_index)

? ? ? ? #1、先把爬主頁的任務(wù)(get_index)異步提交到線程池#2丹拯、get_index任務(wù)執(zhí)行完后站超,會通過回調(diào)函add_done_callback()數(shù)通知主線程,任務(wù)完成乖酬;#2死相、把get_index執(zhí)行結(jié)果(注意線程執(zhí)行結(jié)果是對象,調(diào)用res=res.result()方法咬像,才能獲取真正執(zhí)行結(jié)果)算撮,當(dāng)做參數(shù)傳給parse_index#3生宛、parse_index任務(wù)執(zhí)行完畢后,#4肮柜、通過循環(huán)陷舅,再次把獲取詳情頁 get_detail()任務(wù)提交到線程池執(zhí)行if__name__=='__main__':

? ? main()


涉及知識:多線程多進(jìn)程

計(jì)算密集型任務(wù):使用多進(jìn)程,因?yàn)槟躊ython有GIL审洞,多進(jìn)程可以利用上CPU多核優(yōu)勢莱睁;

IO密集型任務(wù):使用多線程,做IO切換節(jié)省任務(wù)執(zhí)行時間(并發(fā))

線程池

多說一句芒澜,很多人學(xué)Python過程中會遇到各種煩惱問題仰剿,沒有人解答容易放棄。小編是一名python開發(fā)工程師痴晦,這里有我自己整理了一套最新的python系統(tǒng)學(xué)習(xí)教程南吮,包括從基礎(chǔ)的python腳本到web開發(fā)、爬蟲誊酌、數(shù)據(jù)分析旨袒、數(shù)據(jù)可視化、機(jī)器學(xué)習(xí)等术辐。想要這些資料的可以關(guān)注小編砚尽,并在后臺私信小編:“01”即可領(lǐng)取。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辉词,一起剝皮案震驚了整個濱河市必孤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瑞躺,老刑警劉巖敷搪,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異幢哨,居然都是意外死亡赡勘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門捞镰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闸与,“玉大人,你說我怎么就攤上這事岸售〖#” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵凸丸,是天一觀的道長拷邢。 經(jīng)常有香客問我,道長屎慢,這世上最難降的妖魔是什么瞭稼? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任忽洛,我火速辦了婚禮,結(jié)果婚禮上环肘,老公的妹妹穿的比我還像新娘脐瑰。我一直安慰自己,他們只是感情好廷臼,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绝页,像睡著了一般荠商。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上续誉,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天莱没,我揣著相機(jī)與錄音,去河邊找鬼酷鸦。 笑死饰躲,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的臼隔。 我是一名探鬼主播嘹裂,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼摔握!你這毒婦竟也來了寄狼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤氨淌,失蹤者是張志新(化名)和其女友劉穎泊愧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盛正,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡删咱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了豪筝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痰滋。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖续崖,靈堂內(nèi)的尸體忽然破棺而出即寡,到底是詐尸還是另有隱情,我是刑警寧澤袜刷,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布聪富,位于F島的核電站,受9級特大地震影響著蟹,放射性物質(zhì)發(fā)生泄漏墩蔓。R本人自食惡果不足惜梢莽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奸披。 院中可真熱鬧昏名,春花似錦、人聲如沸阵面。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽样刷。三九已至仑扑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間置鼻,已是汗流浹背镇饮。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留箕母,地道東北人储藐。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像嘶是,于是被迫代替她去往敵國和親钙勃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容