作者:蚍蜉撼大樹

0x01 前言

一般而言,抓取稍微正規一點的網站,都會有反爬蟲的製約。反爬蟲主要有以下幾種方式:

  1. 通過UA判斷。這是最低級的判斷,一般反爬蟲不會用這個做唯一判斷,因為反反爬蟲非常容易,直接隨機UA即可解決。
  2. 通過單IP頻繁訪問判斷。這個判斷簡單,而且反反爬蟲比較費力,反爬蟲絕佳方案。需採用多IP抓取。
  3. 通過Cookie判斷,例如通過會員制賬號密碼登陸,判斷單賬號短時間抓取次數判斷。這個反反爬蟲也很費力。需採用多賬號抓取。
  4. 動態頁面加載。這個考驗前端工程師的功底,如果前端寫的好,各種JS判斷,各種邏輯,像百度,淘寶一樣,post登錄很難。較好的方法,但是對於大牛,還是防不勝防。反反爬蟲多采用渲染瀏覽器抓取,效率低下。
  5. 採用驗證碼。這裡要么是登錄的時候有驗證碼,要么是判斷是爬蟲時,不封IP,而是採用驗證碼驗證,例如鍊家網。驗證碼是反爬蟲性價比較高的方案。反反爬蟲一般接入OCR驗證碼識別平台或者人工打碼平台,亦或者利用Tesseract OCR識別,亦或者採用神經網絡訓練識別驗證碼等。

0x02 概要

今天我們先主要來講一講,如何應對第2條的反反爬蟲,如何通過多IP抓取。

通過多IP爬蟲,又分為以下幾種形式:

  1. 通過ADSL撥號換IP。每撥一次就會有一個新IP,較好解決IP單一問題。
  2. 如果是局域網,帶路由器的,第一種方法可能不好用。這個時候可以模擬登陸路由器,控制路由器重新撥號,換IP,這其實是一種折中的辦法,曲線救國。
  3. 代理IP,利用購買的或者網上抓取的免費代理IP,實現多IP爬蟲。
  4. 分佈式爬蟲。採用多個服務器,多個IP,多個slave爬蟲同時運行,由master負責調度。效率較高,屬於大型分佈式抓取,一般用redis分佈式抓取,不表。
  5. 最近了解到一種新的加密的代理網絡。Tor匿名網絡,利用這個也能匿名換IP。這個還沒有詳細了解,不表。

0x03 正文

1. ADSL撥號

我一般是在windows平台ADSL撥號,其他平台暫時沒用過。windows平台撥號,我一般用python的代碼為:

# -*- coding: utf-8 -*-
import os

g_adsl_account = {"name": u"宽带连接",
                "username": "xxxx",
                "password": "xxxx"}
 
     
class Adsl(object):
    # =============================
    # __init__ : name: adsl名称
    # =============================
    def __init__(self):
        self.name = g_adsl_account["name"]
        self.username = g_adsl_account["username"]
        self.password = g_adsl_account["password"]
 
         
    # =============================
    # set_adsl : 修改adsl设置
    # =============================
    def set_adsl(self, account):
        self.name = account["name"]
        self.username = account["username"]
        self.password = account["password"]
 
     
    # =============================
    # connect : 宽带拨号
    # =============================
    def connect(self):
        cmd_str = "rasdial %s %s %s" % (self.name, self.username, self.password)
        os.system(cmd_str)
        time.sleep(5)


    # =============================
    # disconnect : 断开宽带连接
    # =============================
    def disconnect(self):
        cmd_str = "rasdial %s /disconnect" % self.name
        os.system(cmd_str)
        time.sleep(5)
 
     
    #=============================
    # reconnect : 重新进行拨号
    #=============================
    def reconnect(self):
        self.disconnect()
        self.connect()

2. 路由器撥號

如果是局域網,帶路由器的。直接調用windows的rasdial命令無法撥號時,這個時候可以模擬登陸路由器,控制路由器重新撥號,換IP,這其實是一種折中的辦法,曲線救國。下面以登錄小米路由器示例:

# -*- coding: utf-8 -*-
import requests
import urllib
from Crypto.Hash import SHA
import time
import json
import re
import random
import datetime


class Adsl():
    def __init__(self):
        self.host = '192.168.31.1/'
        self.username = 'admin'
        self.password = 'huangxin250'

    def connect(self):
        host = self.host
        homeRequest = requests.get('http://' + host + '/cgi-bin/luci/web/home')
        key = re.findall(r'key: \'(.*)\',', homeRequest.text)[0]
        mac = re.findall(r'deviceId = \'(.*)\';', homeRequest.text)[0]
        aimurl = "http://" + host + "/cgi-bin/luci/api/xqsystem/login"
        nonce = "0_" + mac + "_" + str(int(time.time())) + "_" + str(random.randint(1000, 10000))
        pwdtext = self.password
        pwd = SHA.new()
        pwd.update(pwdtext + key)
        hexpwd1 = pwd.hexdigest()
        pwd2 = SHA.new()
        pwd2.update(nonce + hexpwd1)
        hexpwd2 = pwd2.hexdigest()
        data = {
            "logtype": 2,
            "nonce": nonce,
            "password": hexpwd2,
            "username": self.username
        }
        response = requests.post(url=aimurl, data=data, timeout=15)
        resjson = json.loads(response.content)
        token = resjson['token']
        webstop = urllib.urlopen('http://192.168.31.1/cgi-bin/luci/;stok=' + token + '/api/xqnetwork/pppoe_stop')
        #time.sleep(1)
        webstart = urllib.urlopen('http://192.168.31.1/cgi-bin/luci/;stok=' + token + '/api/xqnetwork/pppoe_start')
        date = datetime.datetime.now()
        nowtime = str(date)[:-10]
        print nowtime + ', congratulations, the IP is changed !'

利用這個方法,就實現了用路由器換IP的目的。該方法的缺陷也是很明顯的。就是不像第一種方法那樣通用。基本上一個路由器就得編一套代碼,屬於定制代碼。

3. 代理IP

代理IP是最常見的一種多IP爬蟲方法。在請求Headers中加入代理IP地址,即可實現代理IP抓取。缺陷是爬取速度和代理IP的速度息息相關。而且好的IP費用較高,免費的速度普遍不高。

附上requests抓取攜帶代理IP和selenium抓取攜帶代理IP的代碼。

requests:

# -*- coding: utf-8 -*-
import requests
reload(sys)
sys.setdefaultencoding('utf-8')
type = sys.getfilesystemencoding()
s = requests.session()
proxie = { 
        'http' : 'http://122.193.14.102:80'
    }   
url = 'xxx'

response = s.get(url, verify=False, proxies = proxie, timeout = 20) 
print response.text

selenium:

from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy
from selenium.webdriver.common.proxy import ProxyType
proxy = Proxy(
    {
        'proxyType': ProxyType.MANUAL,
        'httpProxy': 'ip:port'
    }
)

desired_capabilities = DesiredCapabilities.PHANTOMJS.copy()
proxy.add_to_capabilities(desired_capabilities)
driver = webdriver.PhantomJS(
    executable_path="/path/of/phantomjs",
    desired_capabilities=desired_capabilities
    )
driver.get('http://httpbin.org/ip')
print driver.page_source
driver.close()

0x04 尾言

本節主要講了反爬蟲的一些概念,常用的方法,反反爬蟲的一些方法,並且主要介紹了多IP爬蟲的實現方式,屬於爬蟲領域基礎內容。掌握了這些基礎內容,以後爬蟲步伐才能邁得堅實。

End.

 

轉貼自: 36大數據


留下你的回應

以訪客張貼回應

0

在此對話中的人們

熱門標籤雲

訪客 - Case Study Help
訪客 - Do My Medical Dissertation Writing
Do My Medical Dissertation Writing
Pretty helpful material, much thanks for this article
Tutuapp is an app store same as google play store but extends the limits more than google play store...
訪客 - Homework Help
Homework Help I personally like your post, you have shared good article. It will help me in great de...
訪客 - Nordictrack Treadmills Reviews 2018
Nordictrack Treadmills Reviews 2018 Great Information,it has lot for stuff which is informative.I wi...