requests爬取網(wǎng)頁的通用框架

概述

代碼編寫完成時(shí)間:2017.12.28
寫文章時(shí)間:2017.12.29


看完中國大學(xué)MOOC上的爬蟲教程后,覺得自己之前的學(xué)習(xí)完全是野蠻生長,決定把之前學(xué)的東西再梳理一遍,主要是覺得自己寫的程序和老師寫的差別太大,有很多學(xué)習(xí)的地方,決定用老師所教的和自己已有的知識融合,形成新的知識。
爬蟲的第一步當(dāng)然獲取到網(wǎng)頁,所以可以專門寫一個(gè)程序來獲取網(wǎng)頁,以后對此進(jìn)行不斷改進(jìn)就行,不必重復(fù)制造輪子。


準(zhǔn)備

此程序用到的庫主要是requests庫,還有現(xiàn)在的網(wǎng)站一般都有反爬蟲措施,最常見的是檢查瀏覽器的頭部信息,所以對頭部信息進(jìn)行偽裝的操作可以說是很必要的,為此可以引入fake_useragent庫,引入:

from fake_useragent import UserAgent
import requests

編寫

對爬取網(wǎng)頁代碼的編寫,一般都用requests的get方法對網(wǎng)頁進(jìn)行訪問,對于get方法,為了反爬蟲和良好的體驗(yàn),可以增加一些參數(shù)來增加約束:
response = requests.get(url, headers=headers, timeout=10)
發(fā)現(xiàn)對百度首頁的爬取增不增加頭部信息返回的內(nèi)容是不一樣的,增加了之后可以明顯看到返回的內(nèi)容變多和排版更加人性化。
然后要返回text屬性所包含的內(nèi)容,還有一個(gè)很重要的網(wǎng)頁編碼問題,如果編碼設(shè)置的不對,那么返回的text可能是亂碼,因?yàn)楝F(xiàn)在國際上一般都使用UTF-8編碼,所以我直接令網(wǎng)頁的編碼為UTF-8:

response.encoding = 'utf-8'

其實(shí)按照老師的寫法是這樣的:

response.encoding = response.apparent_encoding

但這樣每次都要根據(jù)網(wǎng)頁的源代碼對編碼進(jìn)行判斷,無疑是要花費(fèi)一點(diǎn)時(shí)間的,干脆使用UTF-8這個(gè)萬金油省事,反正requests一般都是用來爬取單個(gè)網(wǎng)站的內(nèi)容,編碼不對再改就行了,沒什么大不了的。
現(xiàn)在基本上能完成對靜態(tài)網(wǎng)頁的訪問并返回源代碼了。


優(yōu)化

沒看視頻之前,我就是寫到上面那一步之后就收工了,因?yàn)橥瓿闪嘶竟δ苈铮峭ㄟ^和老師的學(xué)習(xí),我知道這樣使不行的,因?yàn)檫@樣的代碼不夠健壯,出錯(cuò)了就直接崩潰,現(xiàn)在代碼量少?zèng)]有關(guān)系,但是以后代碼量大了,就會(huì)有很大的麻煩,所以這是非常不好的習(xí)慣,好的程序應(yīng)該有良好的對異常處理功能,然后我引入可能發(fā)生的異常:
from requests import Timeout, HTTPError
Timeout是可能請求超時(shí)的異常,因?yàn)樾@網(wǎng)不穩(wěn)定,這種情況是十分常見的;HTTPError是請求HTTP頁面的時(shí)候可能發(fā)生的異常,比如常見的404錯(cuò)誤。
下面是改進(jìn)的代碼:

from fake_useragent import UserAgent
import requests
from requests import Timeout, HTTPError

ua = UserAgent()    #能夠獲得瀏覽器種類信息的實(shí)例

def get_page(url):
    try:
        headers = {'User-Agent':ua.random}  #隨機(jī)獲得頭部信息
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        response.encoding = 'utf-8'
        return response.text
    except Timeout:
        print('requests timeout')
        get_page(url)
    except HTTPError:
        print('the http error(maybe status is not 200)')
    except:
        print('other error')

url = 'https://www.baidu.com/'
html = get_page(url)
print(html)

通過上述代碼,除了捕獲引入的兩個(gè)異常外,為了保險(xiǎn)起見,把其他的所有異常就統(tǒng)一進(jìn)行了處理,對于超時(shí)異常,就遞歸調(diào)用,重新訪問;還有對返回的response增加了一行代碼判斷:

response.raise_for_status()

作用是如果返回的狀態(tài)碼不是正常的200,就拋出HTTP錯(cuò)誤。
一些網(wǎng)頁不能正常訪問也返回200狀態(tài)碼,真是有毒,這個(gè)有點(diǎn)無解,目前除了人工判斷,還沒有其他辦法。


總結(jié)

一個(gè)簡單的獲取網(wǎng)頁的框架的代碼已經(jīng)完成了,雖然比較“寒酸”,但基本功能也有了,也有對一些異常的處理,健壯性提升了一點(diǎn),直覺上覺得還有許多不足,但是我相信,隨著不斷地進(jìn)步,此程序就可以變得更加完善的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容