爬蟲初步
爬蟲概念
都有哪些語言可以實(shí)現(xiàn)爬蟲
? (1)php, 號(hào)稱世界上最好的語言,可以實(shí)現(xiàn)爬蟲,但做的不好,天生對(duì)多進(jìn)程和多線程支持的不好
? (2)java,可以實(shí)現(xiàn),而且做的非常好,是python爬蟲最主要的競(jìng)爭(zhēng)對(duì)手, 但語言不簡(jiǎn)潔,代碼臃腫,重構(gòu)成本高 (3)c、c++,也可以實(shí)現(xiàn)爬蟲,非常強(qiáng)大,但是不是一個(gè)好的選擇 (4)python,可以實(shí)現(xiàn),號(hào)稱世界上最優(yōu)雅的語言,代碼簡(jiǎn)潔,學(xué)習(xí)成本低,執(zhí)行效率也好,而且還有一個(gè)非常強(qiáng)大的爬蟲框架 scrapy
通用爬蟲
? 例子:百度、谷歌、360、搜狗、必應(yīng)等等,搜索引擎
? 工作: (1)爬取互聯(lián)網(wǎng)所有的數(shù)據(jù) (2)對(duì)數(shù)據(jù)存儲(chǔ)并且處理 (3)給用戶提供檢索服務(wù) 如何讓百度抓取你的網(wǎng)站? (1)靜靜地等待,百度會(huì)和DNS服務(wù)商合作 (2)主動(dòng)提交自己的url (3)在其它網(wǎng)站設(shè)置友情鏈接 我的網(wǎng)站不想讓百度抓??? 君子協(xié)議,口頭協(xié)議,robots協(xié)議 存放到網(wǎng)站的根目錄下,限制搜索引擎可以爬取哪些,不可以爬取哪些
<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" lang="" contenteditable="false" cid="n26" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 0.9em; white-space: normal; display: block; page-break-inside: avoid; text-align: left; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(223, 226, 229); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-position: inherit inherit; background-repeat: inherit inherit;">##### 如何提升網(wǎng)站排名(SEO)</pre>
? (1)pagerank值排名,根據(jù)點(diǎn)擊量、瀏覽量等,相當(dāng)靠譜
? (2)競(jìng)價(jià)排名
<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" lang="" contenteditable="false" cid="n31" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 0.9em; white-space: normal; display: block; page-break-inside: avoid; text-align: left; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(223, 226, 229); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-position: inherit inherit; background-repeat: inherit inherit;">##### 通用爬蟲缺點(diǎn):</pre>
? (1)抓取很多數(shù)據(jù)都是無效的
? (2)不能根據(jù)自己的需求抓取數(shù)據(jù)
聚焦爬蟲
? 根據(jù)自己特定的需求,來抓取指定的數(shù)據(jù)
? 如何實(shí)現(xiàn)聚焦爬蟲? 網(wǎng)頁(yè)的特點(diǎn): (1)網(wǎng)頁(yè)都有自己唯一的url (2)網(wǎng)頁(yè)都是由html組成 (3)網(wǎng)頁(yè)傳輸都是使用http、https協(xié)議
思路:
? (1)給一個(gè)url
? (2)模擬瀏覽器發(fā)送http請(qǐng)求 (3)從html結(jié)構(gòu)中提取指定的數(shù)據(jù),從字符串中根據(jù)規(guī)則提取指定數(shù)據(jù)
開發(fā)環(huán)境:
? windows系統(tǒng),python3.x(64位),sublime編輯器,pycharm,vscode
整體內(nèi)容:
? (1)涉及到的python庫(kù)
? urllib,requests,selenium,jsonpath,lxml等一些庫(kù) (2)解析內(nèi)容 正則表達(dá)式解析,bs4解析,xpath解析,jsonpath解析 (3)采集動(dòng)態(tài)html DOM操作,動(dòng)態(tài)的添加或者刪除節(jié)點(diǎn),selenium+phantomjs (4)scrapy框架 異步高性能網(wǎng)絡(luò)爬蟲框架的學(xué)習(xí) (5)scrapy-redis分布式部署 在scrapy的基礎(chǔ)上,多了一套分布式部署的組件 (6)涉及到的爬蟲-反爬蟲-反反爬蟲之間的斗爭(zhēng) 反爬會(huì)傷害真實(shí)的用戶,一般情況下,反爬也就這么兩點(diǎn):第一個(gè)UA,第二個(gè)封ip,第三個(gè)驗(yàn)證碼,光學(xué)識(shí)別,打碼平臺(tái) 換思路解決問題:其他網(wǎng)站,手機(jī)端等
關(guān)于http協(xié)議
http和https的區(qū)別
? HTTPS和HTTP的區(qū)別主要如下: 1、https協(xié)議需要到ca申請(qǐng)證書,一般免費(fèi)證書較少,因而需要一定費(fèi)用。 2、http是超文本傳輸協(xié)議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協(xié)議。 3、http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。 4、http的連接很簡(jiǎn)單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。
加密:公鑰私鑰
? 客戶端:123456用秘鑰加密=======》服務(wù)端:用秘鑰解密得到123456 秘鑰相同稱之為對(duì)稱加解密 秘鑰不相同稱之為非對(duì)稱加解密 客戶端:123456用公鑰加密=======》服務(wù)端:用私鑰解密得到123456 http協(xié)議學(xué)習(xí):
請(qǐng)求:包含請(qǐng)求行、請(qǐng)求頭、請(qǐng)求內(nèi)容
請(qǐng)求行:請(qǐng)求方式、請(qǐng)求資源、協(xié)議版本號(hào)
請(qǐng)求頭:
accept:瀏覽器通過這個(gè)頭告訴服務(wù)器,它所支持的數(shù)據(jù)類型
Accept-Charset: 瀏覽器通過這個(gè)頭告訴服務(wù)器,它支持哪種字符集
Accept-Encoding:瀏覽器通過這個(gè)頭告訴服務(wù)器,支持的壓縮格式
Accept-Language:瀏覽器通過這個(gè)頭告訴服務(wù)器,它的語言環(huán)境
Host:瀏覽器通過這個(gè)頭告訴服務(wù)器,想訪問哪臺(tái)主機(jī)If-Modified-Since: 瀏覽器通過這個(gè)頭告訴服務(wù)器,緩存數(shù)據(jù)的時(shí)間
Referer:瀏覽器通過這個(gè)頭告訴服務(wù)器,客戶機(jī)是哪個(gè)頁(yè)面來的 防盜鏈
Connection:瀏覽器通過這個(gè)頭告訴服務(wù)器,請(qǐng)求完后是斷開鏈接還是何持鏈接
-
X-Requested-With: XMLHttpRequest 代表是ajax的請(qǐng)求
響應(yīng):響應(yīng)行、響應(yīng)頭、響應(yīng)內(nèi)容
響應(yīng)行里面,常見的狀態(tài)碼
200:請(qǐng)求成功 處理方式:獲得響應(yīng)的內(nèi)容,進(jìn)行處理
301:請(qǐng)求到的資源都會(huì)分配一個(gè)永久的URL,這樣就可以在將來通過該URL來訪問此資源 處理方式:重定向到分配的URL
302:請(qǐng)求到的資源在一個(gè)不同的URL處臨時(shí)保存 處理方式:重定向到臨時(shí)的URL
304:請(qǐng)求的資源未更新 處理方式:丟棄,使用本地緩存文件
403:禁止 處理方式:丟棄
404:沒有找到 處理方式:丟棄
405:請(qǐng)求方式不對(duì)
500:服務(wù)器內(nèi)部錯(cuò)誤 服務(wù)器遇到了一個(gè)未曾預(yù)料的狀況,導(dǎo)致了它無法完成對(duì)請(qǐng)求的處理。一般來說,這個(gè)問題都會(huì)在服務(wù)器端的源代碼出現(xiàn)錯(cuò)誤時(shí)出現(xiàn)。
響應(yīng)頭
Location: 服務(wù)器通過這個(gè)頭,來告訴瀏覽器跳到哪里
Server:服務(wù)器通過這個(gè)頭,告訴瀏覽器服務(wù)器的型號(hào)
Content-Encoding:服務(wù)器通過這個(gè)頭,告訴瀏覽器,數(shù)據(jù)的壓縮格式
Content-Length: 服務(wù)器通過這個(gè)頭,告訴瀏覽器回送數(shù)據(jù)的長(zhǎng)度
Content-Language: 服務(wù)器通過這個(gè)頭,告訴瀏覽器語言環(huán)境
Content-Type:服務(wù)器通過這個(gè)頭,告訴瀏覽器回送數(shù)據(jù)的類型
Refresh:服務(wù)器通過這個(gè)頭,告訴瀏覽器定時(shí)刷新
Content-Disposition: 服務(wù)器通過這個(gè)頭,告訴瀏覽器以下載方式打數(shù)據(jù)
Transfer-Encoding:服務(wù)器通過這個(gè)頭,告訴瀏覽器數(shù)據(jù)是以分塊方式回送的
Expires: -1 控制瀏覽器不要緩存
Cache-Control: no-cache
Pragma: no-cache
響應(yīng)內(nèi)容:html、css、js、圖片
抓包工具
(1)谷歌瀏覽器自帶抓包工具 右鍵開發(fā)者工具==》network XHR: XMLHttpReqeust 前端要想發(fā)送ajax請(qǐng)求,通過它創(chuàng)建對(duì)象,發(fā)送請(qǐng)求 query_string_parameters : 請(qǐng)求字符串,get參數(shù) formdata : 如果是post參數(shù)(2)專業(yè)工具,fiddler,charles…… 專業(yè)抓包工具,比谷歌強(qiáng)在了跳轉(zhuǎn)的時(shí)候很多請(qǐng)求都能抓取到 前端要像發(fā)送ajax請(qǐng)求,創(chuàng)建對(duì)象調(diào)用對(duì)象方法需要通過XHR
urllib庫(kù)
? urllib庫(kù)是自帶的python庫(kù),模擬發(fā)送http請(qǐng)求 在python 2系列中使用:urllib urllib2 在python 3系列中使用:urllib
urllib庫(kù)的使用
-
urllib.request 模擬發(fā)送請(qǐng)求
-
urlopen(url) : 向url發(fā)送請(qǐng)求,得到響應(yīng)對(duì)象
<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" lang="python" contenteditable="false" cid="n213" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 0.9em; white-space: normal; display: block; page-break-inside: avoid; text-align: left; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(223, 226, 229); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">import urllib.request
url = 'http://www.baidu.com/'
?
response = urllib.request.urlopen(url)
?
print(response)
print(response.read())</pre>
可以看到結(jié)果如下:
[圖片上傳失敗...(image-6c985d-1533895191853)]
-
print(response.read().decode('utf8')):得到了二進(jìn)制的格式,下一步我們需要使用decode將二進(jìn)制格式解碼為字符串格式
response屬性和方法
print(response.url):拿到請(qǐng)求的url
print(response.headers):拿到請(qǐng)求的headers
print(response.status):拿到請(qǐng)求的狀態(tài)碼
urllib.parse: 處理參數(shù)或者url
urllib.error: 如何處理異常
-
保存到文件
? 將抓取的數(shù)據(jù)保存到文件有兩種方式:
第一種方式:通過with打開文件(注意統(tǒng)一編碼格式)
- <pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" lang="python" contenteditable="false" cid="n249" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 0.9em; white-space: normal; display: block; page-break-inside: avoid; text-align: left; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(223, 226, 229); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 0px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;"># 將獲取的響應(yīng)內(nèi)容保存到文件中
with open('baidu1.html', 'a', encoding='utf8') as fp:
fp.write(response.read().decode('utf8'))
?以二進(jìn)制的格式保存
with open('baidu2.html', 'wb') as fp:
fp.write(response.read())</pre>
第二種方式:直接以二進(jìn)制的格式寫入
<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" lang="python" contenteditable="false" cid="n252" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 0.9em; white-space: normal; display: block; page-break-inside: avoid; text-align: left; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(223, 226, 229); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-position: inherit inherit; background-repeat: inherit inherit;"># 實(shí)現(xiàn)發(fā)送請(qǐng)求,將內(nèi)容寫入文件
urllib.request.urlretrieve(url, 'baidu3.html')</pre>
- urlretrieve(url, filepath) : 向url發(fā)送請(qǐng)求,直接將響應(yīng)寫入到filepath中
-
編碼:
-
字符串格式==》字節(jié)格式
encode('utf8')
-
字節(jié)格式==》字符串格式
decode('gbk')
-
爬取圖片的保存
? 下載圖片:得到圖片的src屬性,就可以將圖片下載到本地
? 有兩種方式,主要是對(duì)圖片是做二進(jìn)制的處理:
<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" lang="python" contenteditable="false" cid="n280" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 0.9em; white-space: normal; display: block; page-break-inside: avoid; text-align: left; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(223, 226, 229); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-position: inherit inherit; background-repeat: inherit inherit;">import urllib.request
?
url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1533639915215&di=1bbd3901c9991b363ac0211dc861a909&imgtype=0&src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2F225a5f3f75d1d4c59532704782eebd25d323fd801e57a-VlY5c4_fw658'
?
第一種方式,發(fā)送請(qǐng)求,獲取響應(yīng)
?
response = urllib.request.urlopen(url)
?
with open('meinv.jpg', 'wb') as fp:
?
fp.write(response.read())
?
第二種方式,
?
urllib.request.urlretrieve(url, 'meinv2.png')</pre>
?