Python爬蟲防封殺方法集合
在爬取的過程中難免發生ip被封和403錯誤等等,這都是網站檢測出你是爬蟲而進行反爬措施,這裡自己總結下如何避免。
方法1:設定等待時間
有一些網站的防範措施可能會因為你快速提交表單而把你當做機器人爬蟲,比如說以非常人的速度下載圖片,登入網站,爬取資訊。
常見的設定等待時間有兩種,一種是顯性等待時間(強制停幾秒),一種是隱性等待時間(看具體情況,比如根據元素載入完成需要時間而等待)
1.顯性等待時間
import time#匯入包time.sleep(3)#設定時間間隔為3秒
而且儘量在夜深人靜的時候進行資料的採集,切記採集不要太快,不然容易讓網站識別出你個非人類
2.隱式等待這裡用到的主要語句,以wait.until()為例比如說形式如下
wait1.until(lambda driver: driver.find_element_by_xpath("//div[@id='link-report']/span"))
上面的語句就是在等待頁面元素載入全部完成後才進行下一步操作,因為爬蟲速度太快,導致一些元素沒有被載入完全就進行下一步操作而導致沒有查詢到元素或者被網站認為是機器人在進行瀏覽。
具體的案例可以在我以前的文章中詳細應用Python自定義豆瓣電影種類,排行,點評的爬取與儲存(進階下)
方法2:修改請求頭
識別你是機器人還是人類瀏覽器瀏覽的重要依據就是User-Agent,比如人類用瀏覽器瀏覽就會使這個樣子的User-Agent:'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'
這裡拿urllib2來說,預設的User-Agent是Python-urllib2/2.7,所以要進行修改。
import urllib2 req = urllib2.Request(url)#多了以下一這一步而已req.add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36') response = urllib2.urlopen(req)
方法3:採用代理ip
當自己的ip被網站封了之後,只能採取換代理ip的方式進行爬取,所以,我建議,每次爬取的時候儘量用代理來爬,封了代理,還有代理,無窮無盡啊,可別拿代理去黑學校網站啊,你懂得0.0廢話不多說,扔上代理的實現程式
# -*- coding: utf-8 -*- import urllib2 url = " www.ip181.com/"proxy_support = urllib2.ProxyHandler({'http':'121.40.108.76'}) #引數是一個字典{'型別':'代理ip:埠號'} opener = urllib2.build_opener(proxy_support) #定製opener opener.add_handler=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36')]#add_handler給加上偽裝 urllib2.install_opener(opener) response = urllib2.urlopen(url) print response.read().decode('gbk')
這裡採用的測試網站是 www.ip181.com, 它可以檢測出你使用的ip是什麼,正好來檢驗自己是否用代理ip成功
Python爬蟲防封殺方法集合
使用代理ip訪問
從結果中可以看出,檢測出了代理ip,正是我自己加上的ip值,此乃最後一招,當自己ip被封后,採用代理ip進行訪問。要是一個代理ip掛了怎麼辦,那你可以做個ip池啊,就是把一堆代理ip放在一起,每次執行時從ip池挑一個代理ip當做訪問ip就可以了!
採用ip池的方法~舉個栗子
# -*- coding: utf-8 -*- import urllib2 import random ip_list=['119.6.136.122','114.106.77.14'] #使用一組ip呼叫random函式來隨機使用其中一個ip url = " www.ip181.com/"proxy_support = urllib2.ProxyHandler({'http':random.choice(ip_list)}) #引數是一個字典{'型別':'代理ip:埠號'} opener = urllib2.build_opener(proxy_support) #定製opener opener.add_handler=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36')]#add_handler給加上偽裝 urllib2.install_opener(opener) response = urllib2.urlopen(url) print response.read().decode('gbk')
Python爬蟲防封殺方法集合
使用ip池抽取ip訪問
採用代理ip池的方法,可以看出,檢測出的ip是ip池中的一個,對吧,很簡單對不對,那麼怎麼來建立ip池呢,也很簡單,用BS4隨便找個匿名ip的網站進行代理ip爬取,然後清洗一下ip,把能用的留下來寫到列表裡,然後就可以形成ip池啦,最後當某個ip不能用了,那就從池中剔除!ip池製作,建議參考@七夜的故事--代理ip池
方法4:避開不可見元素陷阱
自己爬著爬著就把隱藏元素都爬出來了,你說你自己是不是爬蟲吧,這是網站給爬蟲的陷阱,只要發現,立馬封IP,所以請檢視一下元素再進行爬取!比如說這個網址,一個簡單的登入頁面,從審查元素中我們可以看到有一些元素是不可見的!(例子抄自python網路資料採集第12章)
Python爬蟲防封殺方法集合
上述中可以看到隱藏的value和不顯示的url
查找出陷阱url和不可見的value程式碼
from selenium import webdriver#from selenium.webdriver.remote.webelement import WebElementurl = ' pythonscraping.com/pages/itsatrap.html'driver = webdriver.PhantomJS(executable_path="phantomjs.exe") driver.get(url) links = driver.find_elements_by_tag_name("a")for link in links:if not link.is_displayed():print "the link "+link.get_attribute("href")+"is a trap"fields = driver.find_elements_by_tag_name("input")for field in fields:if not field.is_displayed():print "do not change value of "+field.get_attribute("name")
結果就是
the link pythonscraping.com/dontgohereis a trapdo not change value of phonedo not change value of email
方法5:採用分散式爬取
基於Python,scrapy,redis的分散式爬蟲實現框架
分散式爬取,針對比較大型爬蟲系統,實現步驟如下所示1.基本的http抓取工具,如scrapy2.避免重複抓取網頁,如Bloom Filter3.維護一個所有叢集機器能夠有效分享的分散式佇列4.將分散式佇列和Scrapy結合5.後續處理,網頁析取(python-goose),儲存(Mongodb)(知乎上看到的補充一下)
採用Scrapy的例子,請參考這裡基於Scrapy對Dmoz進行抓取
方法6:進行模擬登陸
這個就太多了,一般用Selenium,可以結合Firefox或者是無頭瀏覽器PhantomJS,這個做的東西比較多了,如果感興趣,可以點選這些,進行檢視,方法,程式碼,解析,一應俱全
- Selenium+PhantomJS自動續借圖書館書籍(下)
- Python自定義豆瓣電影種類,排行,點評的爬取與儲存(進階下)
- 基於Selenium一鍵寫CSDN部落格
Pay Attention
1.上述實驗的代理ip只對當前資料有效,如果你自己想實驗,請自己選擇比較新的代理ip,我這個ip可能過一段時間就廢了
2.目前我主要採用的方法就是採用加請求頭掛上代理ip的方法,對用JS寫的網站,requests抓不全資料,所以採用Selenium+PhantomJS/Firefox的方法
3.暫且學到這麼多,自己總結了下,以後再補充。
^___^一個程式設計師的淘寶店:點選開啟連結,助你快速學習python技術的一臂之力,不喜歡看廣告的請忽略這條!