首先說一聲,讓大家久等了。本來打算520那天進行更新的,可是一細想,也只有我這樣的單身狗還在做科研,大家可能沒心思看更新的文章,所以就拖到了今天。不過忙了521,522這一天半,我把數據庫也添加進來了,修復了一些bug(現在肯定有人會說果然是單身狗)。(我的新書《Python爬蟲開發與項目實戰》出版了,大家可以看一下樣章)
好了,廢話不多說,咱們進入今天的主題。上兩篇 Scrapy爬取美女圖片 的文章,咱們講解了scrapy的用法。可是就在最近,有熱心的朋友對我說之前的程序無法爬取到圖片,我猜應該是煎蛋網加入了反爬蟲機制。所以今天講解的就是突破反爬蟲機制的上篇 代理ip。
現在很多的網站對反爬蟲的一個做法(當然還有其他檢測)是:檢測一個ip的重復性操作,從而判斷是爬蟲還是人工。所以使用代理ip就可以突破這個封鎖。作為一個學生黨,沒錢專門去買vpn和ip池,所以咱們使用的代理ip來自於網絡上免費的,基本上夠個人使用了。接下來咱們講的是爬取免費ip,並且驗證代理ip的可用性。
網上有很多代理ip的網站,這次我選擇的是http://www.xicidaili.com/nn/,大家學完可以試試其他的網站,咱們努力做個大的代理ip池。
大家是否注意到高匿兩個字,高匿的意思是:對方服務器不知道你使用了代理,更不知道你的真實IP,因此隱蔽性很高。
當真。
按照咱們之前的學習爬蟲的做法,使用firebug審查元素,查看如何解析html。
其實就是一個table,解析里面的每一行,這個很簡單,咱們使用BeautifulSoup很容易就解析出來了。
同時大家還應該注意到,它每一頁上的ip表的頁數和url中的參數是對應的。例如第一頁就是http://www.xicidaili.com/nn/1。這樣就省去了咱們翻頁的麻煩。
以下是程序的結構:
db包中db_helper:實現的是mongodb的增刪改查。
detect包中 detect_proxy:驗證代理ip的可用性
entity包中 proxy_info:對代理信息進行了對象化
spider包:
spiderman 實現爬蟲的邏輯
html_downloader 實現爬蟲的html下載器
html_parser 實現爬蟲的html解析器
test包: 對樣例的測試,不涉及程序運行
main.py:實現命令行參數定義
還要說一下檢測:我是用 http://ip.chinaz.com/getip.aspx作為檢測網址,只要使用代理訪問不超時,而且響應碼為200,咱們就認為是成功的代理。
接下來運行程序看看效果:
在windows下切換到工程目錄,運行python main.py -h,會看到我定義的使用說明和參數設置。
接着運行python main.py -c 1 4 (意思是爬取1-4頁的ip地址):
這時候如果想驗證ip的正確性:運行python main.py -t db
看來好用的ip還是比較少,不過對於個人算是夠用了。
看一下mongodb數據庫:
當咱們下次爬取圖片的時候就可以使用這些ip了。
下面把解析和驗證的代碼貼一下:
def parser(self,html_cont): ''' :param html_cont: :return: ''' if html_cont is None: return # 使用BeautifulSoup模塊對html進行解析 soup = BeautifulSoup(html_cont,'html.parser',from_encoding='utf-8') tr_nodes = soup.find_all('tr',class_ = True) for tr_node in tr_nodes: proxy = proxy_infor() i = 0 for th in tr_node.children: if th.string != None and len(th.string.strip()) > 0: proxy.proxy[proxy.proxyName[i]] = th.string.strip() print 'proxy',th.string.strip() i += 1 if(i>1): break self.db_helper.insert({proxy.proxyName[0]:proxy.proxy[proxy.proxyName[0]],proxy.proxyName[1]:proxy.proxy[proxy.proxyName[1]]},proxy.proxy)
驗證部分核心代碼:
def detect(self): ''' http://ip.chinaz.com/getip.aspx 作為檢測目標 :return: ''' proxys = self.db_helper.proxys.find() badNum = 0 goodNum = 0 for proxy in proxys: ip = proxy['ip'] port = proxy['port'] try: proxy_host ="http://"+ip+':'+port # response = urllib.urlopen(self.url,proxies={"http":proxy_host}) if response.getcode()!=200: self.db_helper.delete({'ip':ip,'port':port}) badNum += 1 print proxy_host,'bad proxy' else: goodNum += 1 print proxy_host,'success proxy' except Exception,e: print proxy_host,'bad proxy' self.db_helper.delete({'ip':ip,'port':port}) badNum += 1 continue print 'success proxy num : ',goodNum print 'bad proxy num : ',badNum
今天的分享就到這里,如果大家覺得還可以呀,記得支持我。代碼上傳到github上:https://github.com/qiyeboy/proxySpider_normal
歡迎大家支持我公眾號:
本文章屬於原創作品,歡迎大家轉載分享。尊重原創,轉載請注明來自:七夜的故事 http://www.cnblogs.com/qiyeboy/