Python 2.7
IDE Pycharm 5.0.3
前言
在爬取的過程中難免發(fā)生ip被封和403錯(cuò)誤等等,這都是網(wǎng)站檢測(cè)出你是爬蟲而進(jìn)行反爬措施,這里自己總結(jié)下如何避免
方法1:設(shè)置等待時(shí)間
有一些網(wǎng)站的防范措施可能會(huì)因?yàn)槟憧焖偬峤槐韱味涯惝?dāng)做機(jī)器人爬蟲,比如說以非常人的速度下載圖片,登錄網(wǎng)站,爬取信息。
常見的設(shè)置等待時(shí)間有兩種,一種是顯性等待時(shí)間(強(qiáng)制停幾秒),一種是隱性等待時(shí)間(看具體情況,比如根據(jù)元素加載完成需要時(shí)間而等待)
1.顯性等待時(shí)間
import time#導(dǎo)入包
time.sleep(3)#設(shè)置時(shí)間間隔為3秒
而且盡量在夜深人靜的時(shí)候進(jìn)行數(shù)據(jù)的采集,切記采集不要太快,不然容易讓網(wǎng)站識(shí)別出你個(gè)非人類
2.隱式等待
這里用到的主要語句,以wait.until()為例
比如說形式如下
wait1.until(lambda driver: driver.find_element_by_xpath("http://div[@id='link-report']/span"))
上面的語句就是在等待頁面元素加載全部完成后才進(jìn)行下一步操作,因?yàn)榕老x速度太快,導(dǎo)致一些元素沒有被加載完全就進(jìn)行下一步操作而導(dǎo)致沒有查找到元素或者被網(wǎng)站認(rèn)為是機(jī)器人在進(jìn)行瀏覽。
具體的案例可以在我以前的文章中詳細(xì)應(yīng)用Python自定義豆瓣電影種類,排行,點(diǎn)評(píng)的爬取與存儲(chǔ)(進(jìn)階下)
方法2:修改請(qǐng)求頭
識(shí)別你是機(jī)器人還是人類瀏覽器瀏覽的重要依據(jù)就是User-Agent,比如人類用瀏覽器瀏覽就會(huì)使這個(gè)樣子的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來說,默認(rèn)的User-Agent是Python-urllib2/2.7,所以要進(jìn)行修改。
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
當(dāng)自己的ip被網(wǎng)站封了之后,只能采取換代理ip的方式進(jìn)行爬取,所以,我建議,每次爬取的時(shí)候盡量用代理來爬,封了代理,還有代理,無窮無盡啊,可別拿代理去黑學(xué)校網(wǎng)站啊,你懂得0.0
廢話不多說,扔上代理的實(shí)現(xiàn)程序
# -*- coding: utf-8 -*-
import urllib2
url = "http://www.ip181.com/"
proxy_support = urllib2.ProxyHandler({'http':'121.40.108.76'})
#參數(shù)是一個(gè)字典{'類型':'代理ip:端口號(hào)'}
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')
這里采用的測(cè)試網(wǎng)站是http://www.ip181.com, 它可以檢測(cè)出你使用的ip是什么,正好來檢驗(yàn)自己是否用代理ip成功
從結(jié)果中可以看出,檢測(cè)出了代理ip,正是我自己加上的ip值,此乃最后一招,當(dāng)自己ip被封后,采用代理ip進(jìn)行訪問。
要是一個(gè)代理ip掛了怎么辦,那你可以做個(gè)ip池啊,就是把一堆代理ip放在一起,每次運(yùn)行時(shí)從ip池挑一個(gè)代理ip當(dāng)做訪問ip就可以了!
采用ip池的方法~~~~~舉個(gè)栗子
# -*- coding: utf-8 -*-
import urllib2
import random
ip_list=['119.6.136.122','114.106.77.14']
#使用一組ip調(diào)用random函數(shù)來隨機(jī)使用其中一個(gè)ip
url = "http://www.ip181.com/"
proxy_support = urllib2.ProxyHandler({'http':random.choice(ip_list)})
#參數(shù)是一個(gè)字典{'類型':'代理ip:端口號(hào)'}
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')
采用代理ip池的方法,可以看出,檢測(cè)出的ip是ip池中的一個(gè),對(duì)吧,很簡(jiǎn)單對(duì)不對(duì),那么怎么來創(chuàng)建ip池呢,也很簡(jiǎn)單,用動(dòng)態(tài)或者靜態(tài)方法隨便找個(gè)匿名ip的網(wǎng)站進(jìn)行代理ip爬取,然后清洗一下ip,把能用的(測(cè)試一個(gè)簡(jiǎn)單的返回狀態(tài)網(wǎng)頁)留下來寫到列表里,然后就可以形成ip池啦,最后當(dāng)某個(gè)ip不能用了,那就從池中剔除!ip池制作,建議參考@七夜的故事--代理ip池
方法4:避開不可見元素陷阱
自己爬著爬著就把隱藏元素都爬出來了,你說你自己是不是爬蟲吧,這是網(wǎng)站給爬蟲的陷阱,只要發(fā)現(xiàn),立馬封IP,所以請(qǐng)查看一下元素再進(jìn)行爬??!
比如說這個(gè)網(wǎng)址,一個(gè)簡(jiǎn)單的登錄頁面,從審查元素中我們可以看到有一些元素是不可見的?。ɡ映詐ython網(wǎng)絡(luò)數(shù)據(jù)采集第12章)
查找出陷阱url和不可見的value代碼
from selenium import webdriver
#from selenium.webdriver.remote.webelement import WebElement
url = 'http://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")
結(jié)果就是
the link http://pythonscraping.com/dontgohereis a trap
do not change value of phone
do not change value of email
方法5:采用分布式爬取
基于Python,scrapy,redis的分布式爬蟲實(shí)現(xiàn)框架
分布式爬取,針對(duì)比較大型爬蟲系統(tǒng),實(shí)現(xiàn)步驟如下所示
1.基本的http抓取工具,如scrapy
2.避免重復(fù)抓取網(wǎng)頁,如Bloom Filter
3.維護(hù)一個(gè)所有集群機(jī)器能夠有效分享的分布式隊(duì)列
4.將分布式隊(duì)列和Scrapy結(jié)合
5.后續(xù)處理,網(wǎng)頁析?。╬ython-goose),存儲(chǔ)(Mongodb)
(知乎上看到的補(bǔ)充一下)
采用Scrapy的例子,請(qǐng)參考這里基于Scrapy對(duì)Dmoz進(jìn)行抓取
方法6:進(jìn)行模擬登陸
這個(gè)就太多了,一般用Selenium,可以結(jié)合Firefox或者是無頭瀏覽器PhantomJS,這個(gè)做的東西比較多了,如果感興趣,可以點(diǎn)擊這些,進(jìn)行查看,方法,代碼,解析,一應(yīng)俱全
- Selenium+PhantomJS自動(dòng)續(xù)借圖書館書籍(下)
- Python自定義豆瓣電影種類,排行,點(diǎn)評(píng)的爬取與存儲(chǔ)(進(jìn)階下)
- 基于Selenium一鍵寫CSDN博客
Pay Attention
1.上述實(shí)驗(yàn)的代理ip只對(duì)當(dāng)前數(shù)據(jù)有效,如果你自己想實(shí)驗(yàn),請(qǐng)自己選擇比較新的代理ip,我這個(gè)ip可能過一段時(shí)間就廢了
2.目前我主要采用的方法就是采用加請(qǐng)求頭掛上代理ip的方法,對(duì)用JS寫的網(wǎng)站,requests抓不全數(shù)據(jù),所以采用Selenium+PhantomJS/Firefox的方法
3.暫且學(xué)到這么多,自己總結(jié)了下,以后再補(bǔ)充。
更新
1.于2016.9.1 14:15進(jìn)行第一次撰寫
2.于2016.9.6 17:48進(jìn)行第二次撰寫
致謝
Python網(wǎng)絡(luò)數(shù)據(jù)采集[Ryan Mitchell著][人民郵電出版社]
@MrLevo520--Python自定義豆瓣電影種類,排行,點(diǎn)評(píng)的爬取與存儲(chǔ)(進(jìn)階下)
@七夜的故事--代理ip池
@MrLevo520--Selenium+PhantomJS自動(dòng)續(xù)借圖書館書籍(下)
@MrLevo520--基于Selenium一鍵寫CSDN博客