我們在做爬蟲的過程中經常會遇到這樣的情況:最初爬蟲正常運行,正常抓取數據,一切看起來都是那麼美好,然而一杯茶的功夫可能就會出現錯誤,比如403Forbidden;這時候網頁上可能會出現:
“您的IP訪問頻率太高”這樣的提示,或者跳出一個驗證碼讓我們輸入,之後才可能解封,但是一會之後又出現這種情況。
出現這個現象的原因是網站採取了一些反爬蟲的措施。比如,服務器會檢測某個IP在單位時間內的請求次數,如果超過了某個閥值,那麼服務器會直接拒絕服務,返回一些錯誤信息。這種情況可以稱為封IP,於是乎網站就成功把我們的爬蟲禁掉了。
試想一下,既然服務器檢測的是某個IP單位時間的請求次數,那麼我們藉助某種方式來偽裝IP,讓服務器無法識別由我們本機發起的請求,這樣不就可以成功防止封IP了嗎?
所以這時候代理就派上用場了。本章會詳細介紹代理的基本知識及各種代理的使用方式,包括代理的設置、代理池的維護、付費代理的使用、ADSL撥號代理的搭建方法等內容,以幫助爬蟲脫離封IP的“苦海”。
我們瞭解了利用代理可以解決目標網站封IP的問題。在網上有大量公開的免費代理,或者我們也可以購買付費的代理IP,但是代理不論是免費的還是付費的,都不能保證都是可用的,因為可能此IP被其他人使用來爬取同樣的目標站點而被封禁,或者代理服務器突然發生故障或網絡繁忙。
一旦我們選用了一個不可用的代理,這勢必會影響爬蟲的工作效率。
所以,我們需要提前做篩選,將不可用的代理剔除掉,保留可用代理。接下來我們就爬取西刺代理的免費代理進行驗證然後存到本地搭建一個高效易用的代理池。
首先我們要發送請求獲取西刺源碼,這裡要注意的是西刺網站也有自己的反爬機制,記得把referer放進請求頭;然後編寫整個請求代碼。
def get_html():
# for x in range(2, 5):
url = "http://www.xicidaili.com/nn/"
header = {
'Remote Address': '123.57.85.224: 443',
'Connection': 'keep - alive',
'Host': 'www.xicidaili.com',
'Referer': 'https://www.xicidaili.com/nn/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
response = requests.get(url, headers=header, timeout=20)
get_proxy(response.text)
資源爬取之後我們對頁面使用xpath進行解析,得到網頁中的ip代理,我們只取ip地址和端口。
看如下代碼:
# 解析網頁,並得到網頁中的IP代理
def get_proxy(html):
selector = etree.HTML(html)
proxies = []
for each in selector.xpath("//tr[@class='odd']"):
ip = each.xpath("./td[2]/text()")[0]
port = each.xpath("./td[3]/text()")[0]
# 拼接IP地址,端口號
proxy = ip + ":" + port
proxies.append(proxy)
print(len(proxies))
緊接著把代理都爬取下來之後再對其進行驗證是否有效。
def test_proxy(proxy):
url = "http://www.baidu.com/"
header = {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
}
try:
response = requests.get(
url, headers=header, proxies={"http": proxy}, timeout=1)
if response.status_code == 200:
print("該代理IP可用:", proxy)
thread_write_proxy(proxy)
else:
print("該代理IP不可用:", proxy)
except Exception:
print("該代理IP無效:", proxy)
pass
看結果:
驗證完成之後把可用的代理保存到本地文件中。
def thread_write_proxy(proxy):
with open("./ip_proxy.txt", 'a+') as f:
print("正在寫入:", proxy)
f.write(proxy + '\\n')
print("錄入完成!!!")
這樣搭建好了我們的一個代理池,以後需要的時候直接使用這些代理就可以了。我們還可以對程序進行一個改進,在驗證IP是否可用的程序是串行的,因此只能驗證一個結束後,才進行驗證下一個,效率極低。我們可以把它改成多線程,提高我們的一個效率。
def thread_test_proxies(proxies):
proxies = proxies
# print("test_proxies函數開始運行。。。\\n", proxies)
for proxy in proxies:
test = threading.Thread(target=test_proxy, args=(proxy,))
test.start()
關於爬蟲的小技巧,你學會了嗎?
本頭條號接下來會發送更多關於python的乾貨、技能知識,想免費學習的小夥伴別忘記關注我們哦~
閱讀更多 行家網校 的文章