反反爬蟲利器!教你怎麼用代理,撥號換IP……
0x01 前言
一般而言,抓取稍微正規一點的網站,都會有反爬蟲的制約。反爬蟲主要有以下幾種方式:
- 通過UA判斷。這是最低級的判斷,一般反爬蟲不會用這個做唯一判斷,因為反反爬蟲非常容易,直接隨機UA即可解決。
- 通過單IP頻繁訪問判斷。這個判斷簡單,而且反反爬蟲比較費力,反爬蟲絕佳方案。需採用多IP抓取。
- 通過Cookie判斷,例如通過會員制賬號密碼登陸,判斷單賬號短時間抓取次數判斷。這個反反爬蟲也很費力。需採用多賬號抓取。
- 動態頁面載入。這個考驗前端工程師的功底,如果前端寫的好,各種JS判斷,各種邏輯,像百度,淘寶一樣,post登錄很難。較好的方法,但是對於大牛,還是防不勝防。反反爬蟲多採用渲染瀏覽器抓取,效率低下。
- 採用驗證碼。這裡要麼是登錄的時候有驗證碼,要麼是判斷是爬蟲時,不封IP,而是採用驗證碼驗證,例如鏈家網。驗證碼是反爬蟲性價比較高的方案。反反爬蟲一般接入OCR驗證碼識別平台或者人工打碼平台,亦或者利用Tesseract OCR識別,亦或者採用神經網路訓練識別驗證碼等。
0x02 概要
今天我們先主要來講一講,如何應對第2條的反反爬蟲,如何通過多IP抓取。
通過多IP爬蟲,又分為以下幾種形式:
- 通過ADSL撥號換IP。每撥一次就會有一個新IP,較好解決IP單一問題。
- 如果是區域網,帶路由器的,第一種方法可能不好用。這個時候可以模擬登陸路由器,控制路由器重新撥號,換IP,這其實是一種折中的辦法,曲線救國。
- 代理IP,利用購買的或者網上抓取的免費代理IP,實現多IP爬蟲。
- 分散式爬蟲。採用多個伺服器,多個IP,多個slave爬蟲同時運行,由master負責調度。效率較高,屬於大型分散式抓取,一般用redis分散式抓取,不表。
- 最近了解到一種新的加密的代理網路。Tor匿名網路,利用這個也能匿名換IP。這個還沒有詳細了解,不表。
0x03 正文
1. ADSL撥號
我一般是在windows平台ADSL撥號,其他平台暫時沒用過。windows平台撥號,我一般用python的代碼為:
# -*- coding: utf-8 -*-nimport osnng_adsl_account = {"name": u"寬頻連接",n "username": "xxxx",n "password": "xxxx"}n n nclass Adsl(object):n # =============================n # __init__ : name: adsl名稱n # =============================n def __init__(self):n self.name = g_adsl_account["name"]n self.username = g_adsl_account["username"]n self.password = g_adsl_account["password"]n n n # =============================n # set_adsl : 修改adsl設置n # =============================n def set_adsl(self, account):n self.name = account["name"]n self.username = account["username"]n self.password = account["password"]n n n # =============================n # connect : 寬頻撥號n # =============================n def connect(self):n cmd_str = "rasdial %s %s %s" % (self.name, self.username, self.password)n os.system(cmd_str)n time.sleep(5)nnn # =============================n # disconnect : 斷開寬頻連接n # =============================n def disconnect(self):n cmd_str = "rasdial %s /disconnect" % self.namen os.system(cmd_str)n time.sleep(5)n n n #=============================n # reconnect : 重新進行撥號n #=============================n def reconnect(self):n self.disconnect()n self.connect()n
2. 路由器撥號
如果是區域網,帶路由器的。直接調用windows的rasdial命令無法撥號時,這個時候可以模擬登陸路由器,控制路由器重新撥號,換IP,這其實是一種折中的辦法,曲線救國。下面以登錄小米路由器示例:
# -*- coding: utf-8 -*-nimport requestsnimport urllibnfrom Crypto.Hash import SHAnimport timenimport jsonnimport renimport randomnimport datetimennnclass Adsl():n def __init__(self):n self.host = 192.168.31.1/n self.username = adminn self.password = huangxin250nn def connect(self):n host = self.hostn homeRequest = requests.get(http:// + host + /cgi-bin/luci/web/home)n key = re.findall(rkey: (.*),, homeRequest.text)[0]n mac = re.findall(rdeviceId = (.*);, homeRequest.text)[0]n aimurl = "http://" + host + "/cgi-bin/luci/api/xqsystem/login"n nonce = "0_" + mac + "_" + str(int(time.time())) + "_" + str(random.randint(1000, 10000))n pwdtext = self.passwordn pwd = SHA.new()n pwd.update(pwdtext + key)n hexpwd1 = pwd.hexdigest()n pwd2 = SHA.new()n pwd2.update(nonce + hexpwd1)n hexpwd2 = pwd2.hexdigest()n data = {n "logtype": 2,n "nonce": nonce,n "password": hexpwd2,n "username": self.usernamen }n response = requests.post(url=aimurl, data=data, timeout=15)n resjson = json.loads(response.content)n token = resjson[token]n webstop = urllib.urlopen(http://192.168.31.1/cgi-bin/luci/;stok= + token + /api/xqnetwork/pppoe_stop)n #time.sleep(1)n webstart = urllib.urlopen(http://192.168.31.1/cgi-bin/luci/;stok= + token + /api/xqnetwork/pppoe_start)n date = datetime.datetime.now()n nowtime = str(date)[:-10]n print nowtime + , congratulations, the IP is changed !n
利用這個方法,就實現了用路由器換IP的目的。該方法的缺陷也是很明顯的。就是不像第一種方法那樣通用。基本上一個路由器就得編一套代碼,屬於定製代碼。
3. 代理IP
代理IP是最常見的一種多IP爬蟲方法。在請求Headers中加入代理IP地址,即可實現代理IP抓取。缺陷是爬取速度和代理IP的速度息息相關。而且好的IP費用較高,免費的速度普遍不高。
附上requests抓取攜帶代理IP和selenium抓取攜帶代理IP的代碼。
requests:
# -*- coding: utf-8 -*-nimport requestsnreload(sys)nsys.setdefaultencoding(utf-8)ntype = sys.getfilesystemencoding()ns = requests.session()nproxie = { n http : http://122.193.14.102:80n } nurl = xxxnnresponse = s.get(url, verify=False, proxies = proxie, timeout = 20) nprint response.textn
selenium:
from selenium import webdrivernfrom selenium.webdriver.common.proxy import Proxynfrom selenium.webdriver.common.proxy import ProxyTypenproxy = Proxy(n {n proxyType: ProxyType.MANUAL,n httpProxy: ip:portn }n)nndesired_capabilities = DesiredCapabilities.PHANTOMJS.copy()nproxy.add_to_capabilities(desired_capabilities)ndriver = webdriver.PhantomJS(n executable_path="/path/of/phantomjs",n desired_capabilities=desired_capabilitiesn )ndriver.get(http://httpbin.org/ip)nprint driver.page_sourcendriver.close()n
0x04 尾言
本節主要講了反爬蟲的一些概念,常用的方法,反反爬蟲的一些方法,並且主要介紹了多IP爬蟲的實現方式,屬於爬蟲領域基礎內容。掌握了這些基礎內容,以後爬蟲步伐才能邁得堅實。
接下來,我還會談一談如何應對驗證碼的反爬蟲,敬請期待~
歡迎關注我的微信公眾號:一隻IT汪。文章將會首發於公眾號,並且我將不定期分享和更新各種IT知識,謝謝!
推薦閱讀: