Scrapy 教程(六)-反爬

假裝瀏覽器

服務器能夠查看訪問的終端,若是不是瀏覽器,可能會被屏蔽,並且即便你用同一瀏覽器訪問頻率過快,也可能被屏蔽,因此須要假裝瀏覽器反爬。html

 

有如下幾種方法python

1. 在 settings中添加 user_agent

#USER_AGENT = 'qiushi (+http://www.yourdomain.com)'
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:66.0) Gecko/20100101 Firefox/66.0'

也能夠添加其餘headerredis

DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html, application/xhtml+xml, application/xml',
  'Accept-Language': 'zh-CN,zh;q=0.8',
  'Host':'ip84.com',
  'Referer':'http://ip84.com/',
  'X-XHR-Referer':'http://ip84.com/'
}

 

 

2. 重寫中間件

在原有 middlewares.py 中重寫中間件,或者新建文件重寫,均可以,最終在settings中設置就好了。數據庫

能夠準備多個瀏覽器,每次訪問隨機選一個json

from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
class UserAgent(UserAgentMiddleware):def process_request(self, request, spider):
        user_agent_list = [
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 "
        "(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 "
        "(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 "
        "(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 "
        "(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 "
        "(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 "
        "(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 "
        "(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 "
        "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 "
        "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"]
        ua = random.choice(user_agent_list)
        if ua:
            request.headers.setdefault('User-Agent', ua)

注意 這裏繼承了 自帶的 UserAgentMiddleware瀏覽器

 

settings設置服務器

DOWNLOADER_MIDDLEWARES = {
   'qiushi.middlewares.UserAgent':1,
   'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware':None}

None 表示關閉該中間件,注意這個中間件須要關閉scrapy自帶的,其餘的不必定須要。cookie

假裝瀏覽器中間件的優先級儘可能高一點。網絡

 

限制訪問頻率

下降訪問目標網站的頻率,很簡單,本身也能夠實現,在scrapy中只需修改settingsapp

DOWNLOAD_DELAY = 3

 

這樣作有個問題,雖然延遲訪問,可是不能動態改變,規則訪問也容易被視爲爬蟲,此時能夠以下配置

RANDOMIZE_DOWNLOAD_DELAY=True

利用一個隨機值,將延遲時間設置爲  0.5-1.5 之間的隨機數 X DOWNLOAD_DELAY

 

但這可能仍然不夠,scrapy 能夠實現自動限速擴展,具體請百度。

 

禁用cookies請求

修改settings

COOKIES_ENABLED = False

若是網站無需登陸就能夠爬取,最好禁用 cookie,由於 cookie 會跟蹤爬蟲的訪問過程,容易被發現

使用網絡代理

用同一個IP頻繁請求一個網站,是很容易被封的。那怎麼辦呢?使用代理是最經常使用的解決方式。

 

須要說明的是:

若是你是用貓來上網,能夠經過重啓更換IP,由於每次重啓會從新分配IP;

若是你不差錢,能夠買不少代理IP,那實現代理爬蟲也很簡單。

 

在有代理的狀況下建立代理爬蟲的方法

建立中間件

class ProxyMiddleware(object):
    def process_request(self, request, spider):
        request.meta['proxy'] = 'http://xx.x.x.x:3128'    

 

修改settings

DOWNLOADER_MIDDLEWARES = {
   'qiushi.middlewares.UserAgent':1,
   'qiushi.middlewares.ProxyMiddleware':100}

沒錯,就是這麼簡單。

 

問題來了,1. 沒錢怎麼辦? 2. 若是代理被封了怎麼辦?

能夠經過爬蟲獲取大量免費代理IP,而後檢測其是否有效

 

建立免費代理爬蟲

免費代理

免費代理須要注意如下幾點:

1. 免費代理不保證能用

2. 即便能用,其存活期也比較短,可能檢測時能用,真正用時已經不能用了

3. 免費代理分爲透明代理匿名代理,須要的是匿名代理 【透明代理好像服務器可以看到你真實IP】

4. 免費代理分爲http型和https型,通常根據目標url選擇,若是目標url爲http類型,只能用http型代理;若是目標url爲https類型,通常用https型代理,也能夠試試http型代理是否能用。【https加密】

5. 比較好的免費代理網站  快代理     西刺代理,使用爬蟲爬蟲該網站

 

檢測代理

如何檢測代理是否有效呢?

1. 專業檢測網站 

http://www.xdaili.cn/monitor

2. 利用urllib2或者request代理檢測,參考個人博客  http://www.javashuo.com/article/p-qattrfqs-ds.html

urllib2 大概是這樣

opener = urllib2.build_opener(urllib2.ProxyHandler({'https':'https://119.99.45.153:9999'}))
urllib2.install_opener(opener)
response = urllib2.urlopen('http://tianqi.2345.com/', timeout=3)
print(response.getcode())

request 大概是這樣

import requests

url = 'http://ip.chinaz.com/'
proxies = {
    'http': 'http://172.16.6.70:3128',
    }
r = requests.get(url, proxies=proxies)
print(r)
print(dir(r))
print(r.headers)

檢測時要注意返回的是否是代理IP,若是代理IP不能用,也會返回,返回的是本身的IP,也就是說 urllib 會搜索環境變量中的代理

3. 固然也有其餘方法

 

很不錯的教程

使用網絡代理實際上會遇到不少坑的,往後慢慢補充。

 

Cookies登陸中間件

利用cookies進行模擬登陸

 

獲取cookie

1. 手動輸入登陸,經過瀏覽器查看cookie

2. 利用selenium模擬登陸,而且用不一樣帳戶,獲取多個cookie,防止cookie被封

 

定義中間件

class LoginMiddleware(object):
    def __init__(self):
        self.client = redis.StrictRedis()
    
    def process_request(self, request, spider):
        if spider.name == 'loginSpider':
            cookies = json.loads(self.client.lpop('cookies').decode())
            request.cookies = cookies

注意最後一句就好了,其餘靈活變通。

 

更pythonic的寫法

1. 把 user-agent-list 、 proxy-list 等寫到 settings 裏,格式還是list【也能夠寫在數據庫等任何能夠的地方,對應方法獲取便可】

2. 在中間件裏導入 settings

3. 調用 settings[‘key’]

 

示例代碼

PROXIES = ['https://114.217.243.25:8118',
          'https://125.37.175.233:8118',
          'http://1.85.116.218:8118']
import random
from scrapy.conf import settings
class ProxyMiddleware(object):
  def process_request(self, request, spider):
      proxy = random.choice(settings['PROXIES'])
      request.meta['proxy'] = proxy
相關文章
相關標籤/搜索