如果你在爬蟲過程中有遇到“您的請求太過頻繁,請稍后再試”渣慕,或者說代碼完全正確嘶炭,可是爬蟲過程中突然就訪問不了,那么恭喜你逊桦,你的爬蟲被對方識破了眨猎,輕則給予友好提示警告,嚴(yán)重的可能會對你的ip進(jìn)行封禁强经,所以代理ip那就尤為重要了睡陪。今天我們就來談一下代理IP,去解決爬蟲被封的問題。
網(wǎng)上有許多代理ip兰迫,免費(fèi)的信殊、付費(fèi)的。大多數(shù)公司爬蟲會買這些專業(yè)版逮矛,對于普通人來說鸡号,免費(fèi)的基本滿足我們需要了转砖,不過免費(fèi)有一個(gè)弊端须鼎,時(shí)效性不強(qiáng),不穩(wěn)定府蔗,所以我們就需要對采集的ip進(jìn)行一個(gè)簡單的驗(yàn)證晋控。
1.目標(biāo)采集
本文主要針對西刺代理,這個(gè)網(wǎng)站很早之前用過姓赤,不過那個(gè)時(shí)候它還提供免費(fèi)的api赡译,現(xiàn)在api暫不提供了,我們就寫個(gè)簡單的爬蟲去采集不铆。
打開西刺代理蝌焚,有幾個(gè)頁面,果斷選擇高匿代理誓斥。
Chrome瀏覽器右鍵檢查查看network只洒,不難發(fā)現(xiàn),每個(gè)ip地址都在td標(biāo)簽中劳坑,對于我們來說就簡單許多了毕谴,初步的想法就是獲取所有的ip,然后校驗(yàn)可用性距芬,不可用就剔除涝开。
- 定義匹配規(guī)則
import re
ip_compile = re.compile(r'<td>(\d+\.\d+\.\d+\.\d+)</td>') # 匹配IP
port_compile = re.compile(r'<td>(\d+)</td>') # 匹配端口
2.校驗(yàn) 這里我使用淘寶ip地址庫檢驗(yàn)可用性
2.1、關(guān)于淘寶IP地址庫
目前提供的服務(wù)包括:
1. 根據(jù)用戶提供的IP地址框仔,快速查詢出該IP地址所在的地理信息和地理相關(guān)的信息舀武,包括國家、省离斩、市和運(yùn)營商银舱。
2. 用戶可以根據(jù)自己所在的位置和使用的IP地址更新我們的服務(wù)內(nèi)容。
我們的優(yōu)勢:
1. 提供國家捐腿、省纵朋、市、縣茄袖、運(yùn)營商全方位信息操软,信息維度廣,格式規(guī)范宪祥。
2. 提供完善的統(tǒng)計(jì)分析報(bào)表聂薪,省準(zhǔn)確度超過99.8%家乘,市準(zhǔn)確度超過96.8%,數(shù)據(jù)質(zhì)量有保障藏澳。
2.2仁锯、接口說明
- 請求接口(GET):
http://ip.taobao.com/service/getIpInfo.php?ip=[ip地址字符串]
例:http://ip.taobao.com/service/getIpInfo2.php?ip=111.177.181.44
- 響應(yīng)信息:
(json格式的)國家 、氏栌啤(自治區(qū)或直轄市)业崖、市(縣)、運(yùn)營商 - 返回?cái)?shù)據(jù)格式:
{"code":0,"data":{"ip":"210.75.225.254","country":"\u4e2d\u56fd","area":"\u534e\u5317",
"region":"\u5317\u4eac\u5e02","city":"\u5317\u4eac\u5e02","county":"","isp":"\u7535\u4fe1",
"country_id":"86","area_id":"100000","region_id":"110000","city_id":"110000",
"county_id":"-1","isp_id":"100017"}}
其中code的值的含義為蓄愁,0:成功双炕,1:失敗。
注意:為了保障服務(wù)正常運(yùn)行撮抓,每個(gè)用戶的訪問頻率需小于10qps妇斤。
我們先通過瀏覽器測試一下
-
輸入地址
http://ip.taobao.com/service/getIpInfo2.php?ip=111.177.181.44
-
再次輸入一個(gè)地址
http://ip.taobao.com/service/getIpInfo2.php?ip=112.85.168.98
代碼操作
import requests
check_api = "http://ip.taobao.com/service/getIpInfo2.php?ip="
api = check_api + ip
try:
response = requests.get(url=api, headers=api_headers, timeout=2)
print("ip:%s 可用" % ip)
except Exception as e:
print("此ip %s 已失效:%s" % (ip, e))
3.代碼
代碼中加入了異常處理,其實(shí)自己手寫的demo寫不寫異常處理都可以丹拯,但是為了方便其他人調(diào)試站超,建議在可能出現(xiàn)異常的地方加入異常處理。
import requests
import re
import random
from bs4 import BeautifulSoup
ua_list = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36",
"Mozilla / 5.0(Windows NT 6.1;WOW64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 45.0.2454.101Safari / 537.36"
]
def ip_parse_xici(page):
"""
:param page: 采集的頁數(shù)
:return:
"""
ip_list = []
for pg in range(1, int(page)):
url = 'http://www.xicidaili.com/nn/' + str(pg)
user_agent = random.choice(ua_list)
my_headers = {
'Accept': 'text/html, application/xhtml+xml, application/xml;',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'zh-CN,zh;q=0.8',
'Referer': 'http: // www.xicidaili.com/nn',
'User-Agent': user_agent
}
try:
r = requests.get(url, headers=my_headers)
soup = BeautifulSoup(r.text, 'html.parser')
except requests.exceptions.ConnectionError:
print('ConnectionError')
else:
data = soup.find_all('td')
# 定義IP和端口Pattern規(guī)則
ip_compile = re.compile(r'<td>(\d+\.\d+\.\d+\.\d+)</td>') # 匹配IP
port_compile = re.compile(r'<td>(\d+)</td>') # 匹配端口
ips = re.findall(ip_compile, str(data)) # 獲取所有IP
ports = re.findall(port_compile, str(data)) # 獲取所有端口
check_api = "http://ip.taobao.com/service/getIpInfo2.php?ip="
for i in range(len(ips)):
if i < len(ips):
ip = ips[i]
api = check_api + ip
api_headers = {
'User-Agent': user_agent
}
try:
response = requests.get(url=api, headers=api_headers, timeout=2)
print("ip:%s 可用" % ip)
except Exception as e:
print("此ip %s 已失效:%s" % (ip, e))
del ips[i]
del ports[i]
ips_usable = ips
ip_list += [':'.join(n) for n in zip(ips_usable, ports)] # 列表生成式
print('第{}頁ip采集完成'.format(pg))
print(ip_list)
if __name__ == '__main__':
xici_pg = input("請輸入需要采集的頁數(shù):")
ip_parse_xici(page=xici_pg)
運(yùn)行代碼:4.為你的爬蟲加入代理ip
建議大家可以把采集的ip存入數(shù)據(jù)庫乖酬,這樣每次爬蟲的時(shí)候直接調(diào)用即可死相,順便提一下代碼中怎么加入代理ip。
import requests
url = 'www.baidu.com'
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36",
}
proxies = {
"http": "http://111.177.181.44:9999",
# "https": "https://111.177.181.44:9999",
}
res = requests.get(url=url, headers=headers, proxies=proxies)
好了剑刑,媽媽再也不擔(dān)心我爬蟲被封了