作者:蚍蜉撼大樹

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

在此對話中的人們

Popular Tags

訪客 - wisozkr
My Friend Recommended This Blog And He Was Totally Right Keep Up The Good Work
Online Medical Thesi...
訪客 - Adam
Finally, we examine the trace plots for the MCMC samples using the
Creative Destruction PC
An Introduction to Greta 在 Joomla 文章
訪客 - Adam
This article provided full information with detailed
Driving Zone 2 Mod Apk
An Introduction to Greta 在 Joomla 文章
訪客 - Adam
So there it is - a Bayesian model using Hamiltonian Monte Carlo sampling
Download Android USB Drive...
An Introduction to Greta 在 Joomla 文章
訪客 - Adam
Congratulation. Greta is a great organization.
Mi Home Apk
An Introduction to Greta 在 Joomla 文章