Python爬蟲403錯誤的終極解決方案
前言
程序使用一段時間后會遇到HTTP Error 403: Forbidden錯誤。 因為在短時間內(nèi)直接使用Get獲取大量數(shù)據(jù),會被服務器認為在對它進行攻擊,所以拒絕我們的請求,自動把電腦IP封了。 解決這個問題有兩種方法。一是將請求加以包裝,變成瀏覽器請求模式,而不再是“赤裸裸”的請求。 但有時服務器是根據(jù)同一IP的請求頻率來判斷的,即使偽裝成不同瀏覽器。由于是同一IP訪問,還是會被封。 所以就有了第二種方法,就是降低請求頻率。具體說來也有兩種方法。一種是在每次請求時暫停短暫時間,從而降低請求頻率。 第二種是使用不同的IP進行訪問。顯然第一種方法不是最佳選擇。 因為我們并不希望下載太慢,尤其是在請求次數(shù)很多時。當然如果間隔很短時間,從感官上并無差別,如0.1秒。 但對于服務器而言頻率就降低了很多。 所以這是一種最安全可靠的辦法,盡管我們并不想用它。第二種方法也就是使用代理IP。下面逐一介紹。
1.增加Header
在瀏覽谷歌地圖時會發(fā)現(xiàn),瀏覽了大量數(shù)據(jù)依然沒有被封IP,但程序中我們只下了幾百張瓦片, 就被封了。主要原因是我們是直接Get請求數(shù)據(jù),而瀏覽器的請求是有Header的。 基于這一點,把請求偽裝成瀏覽器請求,就可以解決這個問題了。 代碼如下:
# coding=utf-8 import urllib2 as ulb import numpy as np import PIL.ImageFile as ImageFile import cv2 import random # 收集到的常用Header my_headers = [ "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)", 'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11', 'Opera/9.25 (Windows NT 5.1; U; en)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)', 'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Kubuntu)', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12', 'Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.2.9', "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Ubuntu/11.04 Chromium/16.0.912.77 Chrome/16.0.912.77 Safari/535.7", "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0 " ] # 獲取影像數(shù)據(jù) def getImage(url): # 用urllib2庫鏈接網(wǎng)絡圖像 response = ulb.Request(url) # 隨機選擇一個Header偽裝成瀏覽器 response.add_header('User-Agent', random.choice(my_headers)) # 打開網(wǎng)絡圖像文件句柄 fp = ulb.urlopen(response) # 定義圖像IO p = ImageFile.Parser() # 開始圖像讀取 while 1: s = fp.read(1024) if not s: break p.feed(s) # 得到圖像 im = p.close() # 將圖像轉(zhuǎn)換成numpy矩陣 arr = np.array(im) # 將圖像RGB通道變成BGR通道,用于OpenCV顯示 pic = np.zeros(arr.shape, np.uint8) pic[:, :, 0] = arr[:, :, 2] pic[:, :, 1] = arr[:, :, 1] pic[:, :, 2] = arr[:, :, 0] return pic img = getImage('https://static.fuwo.com/upload/attachment/1601/08/bea48ebeb5a811e58e9e00163e00254c.jpg') cv2.imshow('image', img) cv2.waitKey(0)
如下所示,獲取到的網(wǎng)絡上的圖片:
但有時這樣的做法也不一定有用。前面也說到,服務器是根據(jù)IP判斷。 給請求增加Header只是偽裝成不同的瀏覽器而已。如果同一個IP在短時間內(nèi)頻繁訪問, 就算是瀏覽器請求也會被拒絕掉。因此對于這個問題就只好從另一個方面著手,即適當降低單個IP訪問頻率。 對于每個IP而言,每次請求操作之間都暫停一段時間。同時利用多個IP進行訪問。通過這兩種手段可以降低被拒絕的可能性。
2.代理IP
簡單地說是通過自動更換不同IP來“迷惑”服務器,讓它認為是來自不同電腦的訪問請求, 從而不會被拒絕掉。由于代理IP的時效性很強,所以需要經(jīng)常更換。最好是“現(xiàn)用現(xiàn)找”。代碼如下:
# coding=utf-8 import urllib2 as ulb import numpy as np import PIL.ImageFile as ImageFile import cv2 import random # 免費代理IP不能保證永久有效,如果不能用可以更新 # https://www.goubanjia.com/ proxy_list = [ '183.95.80.102:8080', '123.160.31.71:8080', '115.231.128.79:8080', '166.111.77.32:80', '43.240.138.31:8080', '218.201.98.196:3128' ] # 獲取影像數(shù)據(jù) def getImage(url): # 隨機從IP列表中選擇一個IP proxy = random.choice(proxy_list) # 基于選擇的IP構(gòu)建連接 urlhandle = ulb.ProxyHandler({'http': proxy}) opener = ulb.build_opener(urlhandle) ulb.install_opener(opener) # 用urllib2庫鏈接網(wǎng)絡圖像 response = ulb.Request(url) # 打開網(wǎng)絡圖像文件句柄 fp = ulb.urlopen(response) # 定義圖像IO p = ImageFile.Parser() # 開始圖像讀取 while 1: s = fp.read(1024) if not s: break p.feed(s) # 得到圖像 im = p.close() # 將圖像轉(zhuǎn)換成numpy矩陣 arr = np.array(im) # 將圖像RGB通道變成BGR通道,用于OpenCV顯示 pic = np.zeros(arr.shape, np.uint8) pic[:, :, 0] = arr[:, :, 2] pic[:, :, 1] = arr[:, :, 1] pic[:, :, 2] = arr[:, :, 0] return pic img = getImage('https://mt2.google.cn/vt/lyrs=s&hl=zh-CN&gl=CN&x=214345&y=107714&z=18') cv2.imshow('image', img) cv2.waitKey(0)
在之前由于過多使用,導致本機IP被封,所以無法訪問Google地圖瓦片,出現(xiàn)如下提示。
運行這段代碼后,就可以成功獲取瓦片,如下所示:
這樣就成功解決訪問瓦片403問題了。代碼列表中的IP就是在這里找的。 網(wǎng)站中還有更多付費的高級功能,如果有需要也可以購買。這里只是簡單測試,就不買了。
3.終極方法
說了上面兩種方法后,很自然地就會想到把兩種方法結(jié)合起來。這樣就會大大提高請求的種類。 如在下面的代碼中Header有13個,IP有6個,排列組合就有78中請求。從理論上來說, 組合數(shù)越多就越不容易被封。同時再加上請求延遲,是較好的解決方案。
# coding=utf-8 import urllib2 as ulb import numpy as np import PIL.ImageFile as ImageFile import cv2 import random import time # 免費代理IP不能保證永久有效,如果不能用可以更新 # https://www.goubanjia.com/ proxy_list = [ '183.95.80.102:8080', '123.160.31.71:8080', '115.231.128.79:8080', '166.111.77.32:80', '43.240.138.31:8080', '218.201.98.196:3128' ] # 收集到的常用Header my_headers = [ "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)", 'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11', 'Opera/9.25 (Windows NT 5.1; U; en)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)', 'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Kubuntu)', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12', 'Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.2.9', "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Ubuntu/11.04 Chromium/16.0.912.77 Chrome/16.0.912.77 Safari/535.7", "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0 " ] # 獲取影像數(shù)據(jù) def getImage(url): # 設置暫停時間為0.1秒 t = 0.1 time.sleep(t) # 隨機從列表中選擇IP、Header proxy = random.choice(proxy_list) header = random.choice(my_headers) print proxy, header # 基于選擇的IP構(gòu)建連接 urlhandle = ulb.ProxyHandler({'http': proxy}) opener = ulb.build_opener(urlhandle) ulb.install_opener(opener) # 用urllib2庫鏈接網(wǎng)絡圖像 response = ulb.Request(url) # 增加Header偽裝成瀏覽器 response.add_header('User-Agent', header) # 打開網(wǎng)絡圖像文件句柄 fp = ulb.urlopen(response) # 定義圖像IO p = ImageFile.Parser() # 開始圖像讀取 while 1: s = fp.read(1024) if not s: break p.feed(s) # 得到圖像 im = p.close() # 將圖像轉(zhuǎn)換成numpy矩陣 arr = np.array(im) # 將圖像RGB通道變成BGR通道,用于OpenCV顯示 pic = np.zeros(arr.shape, np.uint8) pic[:, :, 0] = arr[:, :, 2] pic[:, :, 1] = arr[:, :, 1] pic[:, :, 2] = arr[:, :, 0] return pic img = getImage('https://mt2.google.cn/vt/lyrs=s&hl=zh-CN&gl=CN&x=214345&y=107714&z=18') cv2.imshow('image', img) cv2.waitKey(0)
上述代碼中,將每一次使用的代理IP、Header都輸出到了控制臺中,利用for循環(huán)連續(xù)獲取15次。 輸出的結(jié)果如下:
在上述代碼中使用了請求偽裝、代理IP和請求延遲。 可以看到效果很好,15次請求都沒有被拒絕。以上這些手段只是增加了不被服務器拒絕的概率, 并不代表一定會成功。但相比于不加任何處理的請求,成功幾率高很多。
總結(jié)
到此這篇關于Python爬蟲403錯誤的終極解決方案的文章就介紹到這了,更多相關Python爬蟲403錯誤內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python調(diào)用騰訊云短信服務發(fā)送手機短信
這篇文章主要為大家介紹了Python調(diào)用騰訊云短信服務發(fā)送手機短信,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05Python利用ORM控制MongoDB(MongoEngine)的步驟全紀錄
MongoEngine是一個對象文檔映射器(ODM),相當于一個基于SQL的對象關系映射器(ORM),下面這篇文章主要給大家介紹了關于Python利用ORM控制MongoDB(MongoEngine)的相關資料,需要的朋友可以參考下2018-09-09Python程序中引用環(huán)境變量的方法實現(xiàn)
本文主要介紹了Python程序中引用環(huán)境變量的方法實現(xiàn),通過配置環(huán)境變量并在代碼中引用,可以避免將敏感信息直接寫入代碼中,感興趣的可以了解一下2024-12-12Python 實現(xiàn)數(shù)據(jù)結(jié)構(gòu)-循環(huán)隊列的操作方法
這篇文章主要介紹了Python 實現(xiàn)數(shù)據(jù)結(jié)構(gòu)-循環(huán)隊列的操作方法,需要的朋友可以參考下2019-07-07python解析Chrome瀏覽器歷史瀏覽記錄和收藏夾數(shù)據(jù)
大家好,本篇文章主要講的是python解析Chrome瀏覽器歷史瀏覽記錄和收藏夾數(shù)據(jù),感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下2022-02-02