你的爬蟲又被封了?你真是蠢的可以!用這個不再擔心被封爬蟲!
Spider
當 start_urls 未被指定,會呼叫 start_requests() ,該方法可以用於在爬取資料之前,先進行模擬登陸。
import scrapy from scrapy.http import Request from scrapy.selector import Selector from urllib.parse import urljoin from doubanTop250.items import Doubantop250Item class DoubanTop250Spider(scrapy.spiders.Spider): # 此處為上面留下的小坑 name = "douban" # 設定允許爬取的域名 allowed_domains = ["douban.com"] # header資訊 my_header = { 'Host': 'www.douban.com', 'Referer': 'https://movie.douban.com', } # 表單需要提交的資料 form_data = {'user': 'zone', 'pass': 'zone7'} # 自定義資訊,向下層響應(response)傳遞下去 customer_data = {'key1': 'value1', 'key2': 'value2'} def start_requests(self): return [scrapy.FormRequest("https://movie.douban.com/login", formdata=self.form_data, # 表單提交的資料 headers=self.my_header, method='POST', # GET or POST meta=self.customer_data, # 自定義,向response傳遞資料 errback=self.error_handle, callback=self.logged_in, # 如果需要多次提交表單,且url一樣,那麼就必須加此引數 dont_filter,防止被當成重複網頁過濾掉了 dont_filter=True )] def logged_in(self, response): # 解析模擬登陸資料 pass def parse(self, response): # 預設回撥函式 pass def close(self,reson): # 關閉時呼叫 pass
scrapy.FormRequest 部分引數解析
進群:960410445 獲取原始碼啊!
Middleware
這裡說一下,關於自定義 middleware 需要重寫的幾個方法,可能你看完這一段長篇大論之後,還是懵逼的,沒關係,我也是這樣。不過,當你繼續往下看,看一個例項之後,你就會明白。
process_request(request, spider)
當每個request通過下載中介軟體時,該方法被呼叫。
process_request() 必須返回其中之一: 返回 None 、返回一個 Response 物件、返回一個 Request 物件或 raise IgnoreRequest 。
- 如果其返回 None ,Scrapy將繼續處理該request,執行其他的中介軟體的相應方法,直到合適的下載器處理函式(download handler)被呼叫, 該request被執行(其response被下載)。
- 如果其返回 Response 物件,Scrapy將不會呼叫 任何 其他的 process_request() 或 process_exception() 方法,或相應地下載函式; 其將返回該 response。 已安裝的中介軟體的 process_response() 方法則會在每個 response 返回時被呼叫。
- 如果其返回 Request 物件,Scrapy則停止呼叫 process_request方法並重新排程返回的 request。當新返回的 request 被執行後, 相應地中介軟體鏈將會根據下載的 response 被呼叫。
- 如果其返回一個 Response (可以與傳入的response相同,也可以是全新的物件), 該response會被在鏈中的其他中介軟體的 process_response() 方法處理。
- 如果其返回一個 Request 物件,則中介軟體鏈停止, 返回的request會被重新排程下載。處理類似於 process_request() 返回request所做的那樣。
- 如果其丟擲一個 IgnoreRequest 異常,則呼叫 request 的 errback( Request.errback)。 如果沒有程式碼處理丟擲的異常,則該異常被忽略且不記錄(不同於其他異常那樣)。
引數:
- request (Request 物件) – response 所對應的 request
- response (Response 物件) – 被處理的 response
- spider (Spider 物件) – response 所對應的 spider
process_exception(request, exception, spider)
當下載處理器(download handler)或 process_request() (下載中介軟體)丟擲異常(包括IgnoreRequest異常)時,Scrapy呼叫 process_exception() 。
process_exception() 應該返回以下之一: 返回 None 、 一個 Response 物件、或者一個 Request 物件。
- 如果其返回 None ,Scrapy將會繼續處理該異常,接著呼叫已安裝的其他中介軟體的 process_exception() 方法,直到所有中介軟體都被呼叫完畢,則呼叫預設的異常處理。
- 如果其返回一個 Response 物件,則已安裝的中介軟體鏈的 process_response() 方法被呼叫。Scrapy將不會呼叫任何其他中介軟體的 process_exception() 方法。
- 如果其返回一個 Request 物件, 則返回的request將會被重新呼叫下載。這將停止中介軟體的 process_exception() 方法執行,就如返回一個response的那樣。
引數:
- request (是 Request 物件) – 產生異常的request
- exception (Exception 物件) – 丟擲的異常
- spider (Spider 物件) – request對應的spider
UserAgentMiddleware
多數情況下,網站都會通過 user-agent 來識別訪問的使用者是否為一臺機器,就像爬取豆瓣一樣,如果你沒有設定 user-agent 的話,就會被拒絕訪問。因此,我們只使用一個 user-agent 顯然是不夠的,因此,我們要想個辦法來設定隨機的 user-agent。於是,我們便可以自定義 UserAgentMiddleware 來解決這個問題。
首先,在 setting.py 中新增 user-agent ,如下:
MY_USER_AGENT = [ 'MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23', 'iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)', 'Opera/9.20 (Macintosh; Intel Mac OS X; U; en)', 'Opera/9.0 (Macintosh; PPC Mac OS X; U; en)', 'Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6', 'Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11', 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)', 'Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6', 'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1', 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1', 'Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)' ]
然後在 middlewares.py 中新增如下程式碼:
class MyUserAgentMiddleware(UserAgentMiddleware): def __init__(self, user_agent): self.user_agent = user_agent @classmethod def from_crawler(cls, crawler): return cls( user_agent=crawler.settings.get('MY_USER_AGENT') ) def process_request(self, request, spider): agent = random.choice(self.user_agent) request.headers['User-Agent'] = agent
最後啟用這個 middleware ,在 setting.py 中修改 MyUserAgentMiddleware 的優先順序,如下:
DOWNLOADER_MIDDLEWARES = { # 首先禁止其原有的 UserAgentMiddleware 'scrapy.downloadermiddleware.useragent.UserAgentMiddleware': None, 'doubanTop250.middlewares.MyUserAgentMiddleware': 300, 'doubanTop250.middlewares.ProxyMiddleware': 543, }
ProxyMiddleware
除了要更改 user-agent 之外,我們還要使用 ip 代理來健壯我們的爬蟲程式。那麼,在 scrapy 中如何來設定我們的 ip 代理呢?
首先,在 setting.py 中新增如下程式碼,為代理 ip:
PROXIES = [ "194.186.20.62:21231" , "66.153.222.162:54684" , "219.234.5.128:3128" , "117.114.149.66:53281" , "117.114.149.66:53281" ]
ip 來自西刺代理,不過好像好多沒用的代理。
然後在 middlewares.py 中新增如下程式碼:
from scrapy import signals import random class ProxyMiddleware(object): def __init__(self, ip): self.ip = ip @classmethod def from_crawler(cls, crawler): return cls(ip=crawler.settings.get('PROXIES')) def process_request(self, request, spider): ip = random.choice(self.ip) request.meta['proxy'] = ip
最後啟用這個 middleware ,在 setting.py 中修改 ProxyMiddleware 的優先順序,如下:
DOWNLOADER_MIDDLEWARES = { # 首先禁止其原有的 UserAgentMiddleware 'scrapy.downloadermiddleware.useragent.UserAgentMiddleware': None, 'doubanTop250.middlewares.MyUserAgentMiddleware': 300, 'doubanTop250.middlewares.ProxyMiddleware': 543, }
瞎比比
經過這些操作之後,你的程式碼等級就提升了一個高度了。說了那麼多,我們好像還沒有將我們抓取的資料儲存下來,那麼下一篇文章將會說說如何儲存我們的資料。後臺回覆【007】獲取原始碼。