反爬機制很多,其中一種便是web服務器通過記錄IP訪問服務器的頻率來判斷該IP地址是否為爬蟲IP,為了避免IP被封,同時可以提高爬取數據的穩定性,可以通過第三方IP地址發起請求,為了后期數據爬取的穩定性,可以構建自己的代理池,本程序是通過爬取西刺代理網站里的免費高匿IP,構建后期工作所需的IP代理池工具包,具體程序如下:
注:
1>高匿:高度匿名,web服務器只能看到代理IP地址,無法看到客戶自身地址,更無法識別是否使用代理IP,一切IP均識別為真實客戶IP(爬蟲首選)
2>匿名:web服務器只能看到代理IP地址和使用代理訪問,即web知道有人用代理IP訪問網站而不知道究竟是哪個客戶的IP在訪問
3>透明:web服務器會知道代理IP地址和用戶自身真實IP
import requests from fake_useragent import UserAgent from lxml import etree import random import time class Spider(object): def __init__(self, start, end): self.base_url = 'https://www.xicidaili.com/nn/{}' # 用來存放所有的代理IP self.proxies_list = [] self.start = start self.end = end # 獲取隨機ua def get_random_ua(self): ua = UserAgent() return ua.random # 從西刺代理網站獲取IP def get_ip_list(self, url): # 發請求 html = requests.get(url, headers={'User-Agent': self.get_random_ua()}).text # 解析 parse_html = etree.HTML(html) tr_list = parse_html.xpath('//*[@id="ip_list"]//tr') # print(tr_list) for tr in tr_list[1:]: ip = tr.xpath('./td[2]/text()')[0].strip() port = tr.xpath('./td[3]/text()')[0].strip() proxies = { 'http': 'http://{}:{}'.format(ip, port), 'https': 'https://{}:{}'.format(ip, port), } self.proxies_list.append(proxies) # print(len(self.proxies_list)) # print(self.proxies_list) return self.proxies_list def main(self): for i in range(self.start, self.end + 1): url = self.base_url.format(str(i)) self.get_ip_list(url) time.sleep(random.randint(1, 10)) return self.proxies_list if __name__ == '__main__': spider = Spider(1, 2) proxies_list = spider.main()
假設上述程序放在xici_proxy_pools.py模塊中,現在用其測試一下http://httpbin.org/get網站,要求如下:
1、首先判斷構建的代理池是否為空;
2、當選中的IP在測試時超過時間限制時,則將其刪除,從新在代理池中選取;
代碼如下:
from xici_proxy_pools import * import requests import random from fake_useragent import UserAgent url = 'http://httpbin.org/get' headers = {'User-Agent': UserAgent().random} spider = Spider(1, 3) proxies_list = spider.main() while True: if proxies_list is not None: proxies = random.choice(proxies_list) try: html = requests.get(url, proxies=proxies, headers=headers, timeout=3).text print(html) break except: # 先移除IP proxies_list.remove(proxies) print('{}已經移除'.format(proxies)) continue
再用IP代理池爬取需要客戶端驗證登錄才能爬取網頁內容的網站,代碼如下:
import requests from lxml import etree from fake_useragent import UserAgent from xici_proxy_pools import * import random class NoteSpider(object): def __init__(self): self.base_url = '自己寫' self.headers = {'User-Agent': UserAgent().random} self.auth = ('username', 'password') self.proxies_list = Spider(1, 2).main() # 獲取一級頁面 def get_one_page(self): while True: if self.proxies_list is not None: proxies = random.choice(self.proxies_list) # print(proxies) else: break try: html = requests.get(self.base_url, proxies=proxies, headers=self.headers, auth=self.auth, timeout=5).text self.parse_one_page(html) # print(html) break except: self.proxies_list.remove(proxies) continue # 解析頁面 def parse_one_page(self, html): parse_html = etree.HTML(html) result_list = parse_html.xpath('/html/body/pre/a/text()')[1:] print(result_list) if __name__ == '__main__': spider = NoteSpider() spider.get_one_page()
