一、前言
2020-04-04日爬蟲練習
每日一個爬蟲小練習,學習爬蟲的記得關注哦!
學習編程就像學習騎自行車一樣,對新手來說最重要的是持之以恆的練習。
在《汲取地下水》這一章節中看見的一句話:“別擔心自己的才華或能力不足。持之以恆地練習,才華便會有所增長”,現在想來,真是如此。
二、需求:
分頁爬取快代理國內免費高匿IP,並對IP進行清洗驗證,將可用的IP儲存到本地
三、IP代理池設計
3.1 意義
學習爬蟲,離不開高頻訪問(請求),現在很多網站爲了抵禦爬蟲,設置防爬措施,對頻繁訪問的IP要求重新登錄,或者或跳轉至一個帶有滑塊驗證的頁面,要求用戶登錄或拖動滑塊。目前對於反爬措施中IP限制,使用動態IP代理訪問還是可行的。
3.2 IP代理科普
IP代理有透明代理、匿名代理、混淆代理和高匿代理。這四種代理,主要是代理服務器端的配置不同,導致其向目標地址發送請求時,REMOTE_ADDR、HTTP_VIA、HTTP_X_FORWARDED_FOR三個變量不同。
一:透明代理(Transparent Proxy)
REMOTE_ADDR=Proxy IP
HTTP_VIA=Proxy IP
HTTP_X_FORWARDED_FOR=Your IP
透明代理雖然可以直接”隱藏”你的IP,但是還是可以從HTTP_X_FORWARDED_FOR來查到你是誰。
二:匿名代理(Anonymous Proxy)
REMOTE_ADDR=Proxy IP
HTTP_VIA=Proxy IP
HTTP_X_FORWARDED_FOR=Proxy IP
匿名代理比透明代理進步一點:別人只能知道你用了代理,無法知道你是誰。
三:混淆代理(Distorting Proxies)
REMOTE_ADDR=Proxy IP
HTTP_VIA=Proxy IP
HTTP_X_FORWARDED_FOR=Random IP address
與匿名代理相同,如果使用了混淆代理,別人還是能知道你在用代理,但是會得到一個假的IP地址,僞裝的更逼真
四:高匿代理(High Anonymity Proxy)
REMOTE_ADDR=Proxy IP
HTTP_VIA=not determined
HTTP_X_FORWARDED_FOR=not determined
使用高匿代理,能讓別人根本無法發現你是在用代理,所以是最好的選擇。
3.3 技術路線
1.requests
2.BeautifulSoup
3.threading.Thread # 多線程
3.4 設計思路
- 目前網上有很多免費的代理IP,不過這種免費代理IP都不穩定,獲取到的免費IP都得通過清洗(檢測)是否可用。
- 本博文爬取的是快代理IP的國內高匿IP:https://www.kuaidaili.com/free/
- 由於清洗代理,時間大都花在網絡請求上了,個人試了下多線程爬取,速度有很大提升。
3.5 實戰過程中遇到的問題
1.由於快代理的HTTP 是大寫,直接進行 requests請求的時候, requests請求可以成功,但是請求使用的將會是你真實的ip地址 ,所以得進行大小寫轉換。
2. 如果爬取到的代理IP協議是https,在訪問http網站時,requests請求可以成功,但是請求使用的將會是你真實的ip地址
3. 一開始使用http://icanhazip.com/網站進行驗證,如果正常ip,它返回值的text,將會是你請求IP,但是它對80,8080等一些特殊端口不友好,無法做到正確驗證,而且響應速度慢,特別影響效率。
4. 使用https://www.baidu.com/進行驗證有兩個好處,
----百度支持http和https,所以兩個協議都能使用代理IP進行正常訪問
----百度請求和響應速度特別快,如果狀態碼爲200,那就說明代理ip有效,能起到快速清洗效果
ps:這是我爬蟲實戰過程中遇到的問題,覺得有幫助的給個贊吧!
四、快代理高匿IP爬取清洗實戰:
'''
爬取快代理IP,建設自己的爬蟲代理池
version:01
author:金鞍少年
date:2020-04-04
'''
import requests
from bs4 import BeautifulSoup
import time
from threading import Thread
class Douban:
def __init__(self):
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36',
'Referer': 'https://www.kuaidaili.com/free/'
}
# 獲取分頁html
def get_page_html(self, url):
try:
result = requests.get(url=url, headers=self.headers)
result.raise_for_status() # 主動拋出一個異常
html = BeautifulSoup(result.text, 'lxml')
return html
except:
print('鏈接失敗!')
# 獲取免費ip 信息
def get_proxy(self, html):
proxies = [] # 代理池
trs = html.find('table', class_='table table-bordered table-striped').find('tbody').find_all('tr')
for tr in trs:
tcp = list(tr.stripped_strings)[3].lower()
ip = list(tr.stripped_strings)[0]
port = list(tr.stripped_strings)[1]
proxies.append((tcp, ip+":"+port)) # 拼接IP地址,端口號
return proxies
# 開啓多線程任務
def test_proxies(self, proxies):
proxies = proxies
for proxy in proxies:
test = Thread(target=self.thread_test_proxy, args=(proxy[0], proxy[1],))
test.start()
# 開啓線程驗證ip模式
def thread_test_proxy(self, tcp, address):
try:
print('待驗證ip:%s' % address)
# 因爲TCP分http和https,所以分開傳入做精準驗證
result = requests.get('https://www.baidu.com/', headers=self.headers, proxies={tcp: address}, timeout=3) # timeout 超時時間
if result.status_code == 200:
self.save_proxys((tcp, address)) # 寫入文件
else:
pass
except Exception:
pass
# 保存IP到本地
def save_proxys(self, proxy):
with open("./res/快代理免費高匿IP.text", 'a+') as f:
print('有效IP:【{}:{}】'.format(proxy[0], proxy[1]))
f.write('{}:{}'.format(proxy[0], proxy[1]) + '\n')
# 邏輯功能
def func(self, base_url, page):
for i in range(1, page): # 快代理分頁
try:
time.sleep(1)
url = base_url.format(i)
proxies = self.get_proxy(self.get_page_html(url))
self.test_proxies(proxies)
except Exception as e:
print('錯誤類型:%s' % e)
continue
if __name__ == '__main__':
obj = Douban()
obj.func('https://www.kuaidaili.com/free/inha/{}/', 2) # rul 和爬取分頁數
print('爬取完畢,IP錄入成功!')