Python爬蟲防封殺方法集合

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成功

使用代理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池抽取ip訪問

采用代理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章)

上述中可以看到隱藏的value和不顯示的url

查找出陷阱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)俱全


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博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 爬蟲文章 in 簡(jiǎn)書程序員專題: like:128-Python 爬取落網(wǎng)音樂 like:127-【圖文詳解】py...
    喜歡吃栗子閱讀 22,677評(píng)論 4 411
  • 自己是無意中發(fā)現(xiàn)簡(jiǎn)書這個(gè)軟件的,因?yàn)樽约合矚g寫東西,只是從小時(shí)候就養(yǎng)成了要寫日記,摘抄,筆記的習(xí)慣,所以至...
    墨雪卿多多閱讀 302評(píng)論 1 0
  • 這是一本經(jīng)典的值得推薦的叫你如何學(xué)習(xí)的書籍。 主題就是在怎么樣閱讀方面。是不錯(cuò)的一本指導(dǎo)書,書中作者給出關(guān)于閱讀以...
    SAMSON小黑麥閱讀 235評(píng)論 0 0
  • 莎奈朵閱讀 463評(píng)論 0 0
  • 學(xué)會(huì)提問 《學(xué)會(huì)提問》被譽(yù)為是批判性思維領(lǐng)域的一本圣經(jīng),在美國被譽(yù)為指導(dǎo)批判性思維“最成功的”書籍之一,在國內(nèi),受...
    一枚冰兒閱讀 679評(píng)論 4 1

友情鏈接更多精彩內(nèi)容