好久沒更新博客啦~,今天來更新一篇利用爬蟲爬取西刺的代理池的小代碼
先說下需求,我們都是用python寫一段小代碼去爬取自己所需要的信息,這是可取的,但是,有一些網站呢,對我們的網絡爬蟲做了一些限制,例如你利用python寫了個小爬蟲,巴拉巴拉的一勁兒爬人家網頁內容,各種下載圖片啦,下載視頻啥的,然后人家那肯定不讓你搞了~,然后尷尬的一幕就出現了,什么呢....防火牆!禁止你在某一段時間登錄....給你各種拉黑,那我們有沒有什么辦法,能特么的不讓狗日的拉黑呢,so...我們可以來一些反爬蟲的策略,一般來說,我們可以讓爬蟲爬去網頁的內容盡可能的慢一些,或者封裝自己的headers,也就是使用瀏覽器的headers來偽裝自己,另外一種,我們可以通過"代理"來實現發爬蟲策略,某些網站會對IP地址做限制,例如某個ip地址在一段時間內容訪問網站太TMD的快了,要是我,我特么的也不讓你玩對吧~,so...我們可以通過偽裝ip從而實現繼續爬呀爬呀爬,直到爬死小站點~~~漬漬漬!
好,叨逼完前戲了,咱們進入正題~,本次代碼是基於scarpy1.4+python3.6.1的環境+pymysql來保存ip代理池的信息以及利用requests中的get方法以及proxies來實現代理功能,so...沒TMD模塊的,快去准備吧~
代碼所需環境:
- python 3.6.1
- scrapy 1.4
- requests
- pymysql
代碼分兩部分,第一部分為爬取西刺的免費ip代理保存到數據庫中,第二部分為從數據庫中隨機取免費的ip地址,並且判斷該ip地址的可用性!!!!!
ok,先來第一部分的獲取西刺免費ip代理的代碼~
1 # _*_coding:utf-8_*_ 2 import pymysql 3 import requests 4 from scrapy.selector import Selector 5 6 __author__ = 'demon' 7 8 conn = pymysql.connect(host='mysqls數據庫的ip地址,換成你自己的!', user='登錄MySQL的用戶名', passwd='密碼!', db='xc_proxy(MySQL的數據庫名稱)', charset='utf8') 9 cursor = conn.cursor() 10 11 12 def crawl_ips(): 13 headers = { 14 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " 15 "Chrome/59.0.3071.115 Safari/537.36"} 16 for i in range(1, 1001): 17 url = 'http://www.xicidaili.com/wt/{0}'.format(i) 18 req = requests.get(url=url, headers=headers) 19 selector = Selector(text=req.text) 20 all_trs = selector.xpath('//*[@id="ip_list"]//tr') 21 22 ip_lists = [] 23 for tr in all_trs[1:]: 24 speed_str = tr.xpath('td[7]/div/@title').extract()[0] 25 if speed_str: 26 speed = float(speed_str.split('秒')[0]) 27 ip = tr.xpath('td[2]/text()').extract()[0] 28 port = tr.xpath('td[3]/text()').extract()[0] 29 proxy_type = tr.xpath('td[6]/text()').extract()[0].lower() 30 ip_lists.append((ip, port, speed, proxy_type)) 31 32 for ip_info in ip_lists: 33 cursor.execute( 34 f"INSERT proxy_ip(ip,port,speed,proxy_type) VALUES('{ip_info[0]}','{ip_info[1]}',{ip_info[2]}," 35 f"'{ip_info[3]}') " 36 ) 37 conn.commit()
上面的代碼呀....卧槽,好懵逼 好懵逼,那他媽的各種xpath是毛線呀~~哈哈哈哈,自己去學習xpath的知識吧~~,這些玩意,我打字也說不明白,so...既然說不明白,那TMD干嘛浪費口水~,總之一句話,我們最后需要的ip代理是這種格式的{'http': 'http://113.105.146.77:8086'},這里面包含了協議ip地址以及端口號~,so...我們需要在頁面中提取這些內容,當然,我還提取的速度,因為有些ip地址的速度太TMD慢了~拿來也並沒有什么卵用!算了叨逼叨逼兩句吧~,我們爬取前1000頁中的免費ip地址~然后在代碼中實現了獲取當前的免費ip地址,端口,以及協議及速度~,然后把提取到的每頁中的我們需要的信息到放到一個元祖中,循環每頁中的列表,然后把和免費代理ip相關的信息放到數據庫中~,so....說到數據庫,怕有些人不知道數據庫中字段的類型,放上創建數據庫字段的代碼吧~
創建數據庫及創建存儲免費ip代理的表~
- CREATE DATABASE xc_proxy CHARSET='utf8';
- CREATE TABLE proxy_ip (ip VARCHAR(30) NOT NULL PRIMARY KEY,port VARCAHR(5) NOT NULL,speed FLOAT NULL,proxy_type VARCAHR(10) NULL);
- GRANT ALL PRIVILEGES ON xc_proxy.* TO 'root'@'%' IDENTFIED BY '你要給root用戶設置的登錄密碼';
- FLUSH PRIVILEGES;
proxy_ip表創建成功的信息
ok,上面就是第一步獲取免費的ip地址並保存到數據中~,下面我們要做的就是從數據中隨機取ip地址並進行ip地址的可用性測試~
duang duang duang~,第二部分!
1 class GetIP(object): 2 3 def delete(self,ip): 4 delete_sql = 'DELETE FROM proxy_ip WHERE ip="{0}"'.format(ip) 5 cursor.execute(delete_sql) 6 conn.commit() 7 return True 8 9 def valid_ip(self, ip, port, proxy_type): 10 headers = { 11 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " 12 "Chrome/59.0.3071.115 Safari/537.36"} 13 try: 14 proxies = {proxy_type: proxy_type + '://' + ip + ':' + port} 15 req = requests.get('http://ip.chinaz.com/getip.aspx', headers=headers, proxies=proxies, timeout=3) 16 except: 17 print('invalid ip and port') 18 self.delete(ip) 19 return False 20 else: 21 if 200 <= req.status_code < 300: 22 # print('{0} effective ip~'.format(proxies)) 23 print(req.text) 24 return True 25 else: 26 print('invalid ip and port') 27 self.delete(ip) 28 return False 29 30 @property 31 def get_random_ip(self): 32 random_ip = 'SELECT proxy_type,ip, port FROM proxy_ip ORDER BY RAND() LIMIT 1;' 33 cursor.execute(random_ip) 34 proxy_type, ip, port = cursor.fetchone() 35 valid_ip = self.valid_ip(ip, port, proxy_type) 36 if valid_ip: 37 return {proxy_type: proxy_type + '://' + ip + ':' + port} 38 else: 39 return self.get_random_ip 40 41 if __name__ == '__main__': 42 proxy = GetIP() 43 print(proxy.get_random_ip)
簡單的說一下~寫了三個方法,分別對應的刪除無效的免費ip信息,隨機從數據庫中取ip地址並做免費ip地址的可用性驗證~,實例化類以后,我們調用類中的get_random_ip的方法,從數據中取隨機的免費ip地址,並把獲取到的ip地址通過拆包的方式分別復制給協議,IP以及端口,然后把這三個參數送給valid_ip方法做驗證,如果驗證成功,怎返回True,否者先從數據庫中刪除不能使用的免費ip地址並返回False,如果ip地址不能使用,則繼續調用自己,直到ip地址可用未知,ok..就TMD這些東西,有了這些能用免費ip地址,你就可以拿它,嘿嘿嘿嘿~~~
存放的免費IP地址信息以及數據表結構
多說一句~~免費的ip代理相當的不穩定,如果需要穩定的,那就要充值信仰了,畢竟人民幣玩家才是真愛!