Scrapy框架之代理和cookie

Cookie 是在 HTTP 協議下,服務器或腳本能夠維護客戶工做站上信息的一種方式。Cookie 是由 Web 服務器保存在用戶瀏覽器(客戶端)上的小文本文件,它能夠包含有關用戶的信息。不管什麼時候用戶連接到服務器,Web 站點均可以訪問 Cookie 信息cookie須要我的用戶登陸網站。
  場景需求:獲取用戶我的主頁二級頁面的頁面數據。html

1、Scrapy發起post請求

  要登陸網站,所以必須發送post請求,如何實現發送post請求?
  場景需求:百度翻譯中指定詞條對應的翻譯結果進行獲取。python

一、方法一:重寫start_requests方法來發送post請求

  爬蟲文件中的爬蟲類繼承到了Spider父類中的start_requests(self)這個方法,該方法就能夠對start_urls列表中的url發起請求。
  該方法默認的實現,是對起始的url發起get請求,若是想發起post請求,則須要子類重寫該方法。web

import scrapy

class PostdemoSpider(scrapy.Spider):
    name = 'postDemo'
    # allowed_domains = ['www.baidu.com']
    start_urls = ['https://fanyi.baidu.com/sug']     # 經過抓包找到post請求地址

    def start_requests(self):
        """重寫的父類方法:該方法能夠對star_urls列表中的元素進行get請求發送"""
        for url in self.start_urls:
            # Request方法默認發送get請求,配置method參數賦值爲'post'
            yield scrapy.Request(url=url, callback=self.parse, method='post')

    def parse(self, response):
        pass

二、方法二:利用FormRequest方法來發送post請求(推薦)

(1)編寫爬蟲文件postDemo.py

import scrapy

class PostdemoSpider(scrapy.Spider):
    name = 'postDemo'
    # allowed_domains = ['www.baidu.com']
    start_urls = ['https://fanyi.baidu.com/sug']    # 經過抓包找到post請求地址

    def start_requests(self):
        """重寫的父類方法:該方法能夠對star_urls列表中的元素進行get請求發送"""
        print("start_requests()被調用")
        data = {
            'kw': 'dog',  # post請求參數
        }
        for url in self.start_urls:
            # FormRequest()能夠發送post請求
            # formdata表示請求參數對應的字典
            yield scrapy.FormRequest(url=url, formdata=data, callback=self.parse)

    def parse(self, response):
        print(response.text)

(2)編輯settings.py文件

# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' # 假裝請求載體身份

# Obey robots.txt rules
ROBOTSTXT_OBEY = False    # 不聽從門戶網站robots協議,避免某些信息爬取不到

(3)建立項目、建立應用、執行爬蟲

# 建立項目和應用(後面的項目將再也不描述)
$ scrapy startproject postPro
$ cd postPro/
$ scrapy genspider postDemo www.baidu.com

# 執行爬蟲命令
$ scrapy crawl postDemo --nolog
start_requests()被調用
{"errno":0,"data":[{"k":"dog","v":"n. \u72d7; \u8e69\u811a\u8d27; \u4e11\u5973\u4eba; \u5351\u9119\u5c0f\u4eba; v. \u56f0\u6270; \u8ddf\u8e2a;"},{"k":"dogs","v":"n. \u516c\u72d7( dog\u7684\u540d\u8bcd\u590d\u6570 ); \uff08\u5c24\u7528\u4e8e\u5f62\u5bb9\u8bcd\u540e\uff09\u5bb6\u4f19; [\u673a\u68b0\u5b66]\u5939\u5934; \u4e0d\u53d7\u6b22\u8fce\u7684\u4eba;"},{"k":"doge","v":"n. \u5171\u548c\u56fd\u603b\u7763;"},{"k":"doggy","v":"n. \u5c0f\u72ac\uff0c\u5c0f\u72d7; adj. \u50cf\u72d7\u4e00\u6837\u7684;"},{"k":"doggie","v":"n. \u5c0f\u72d7\uff0c\u72d7\uff0c\u6c6a\u6c6a;"}]}

2、cookie操做

  知道post請求後,來實現最開始的場景需求:獲取用戶我的主頁二級頁面的頁面數據。
  新建項目doubanPro,這裏沒有在管道中處理,簡化操做直接在爬蟲文件中持久化數據保存在文件中,爬蟲文件douban.py以下所示:瀏覽器

import scrapy

class DoubanSpider(scrapy.Spider):
    name = 'douban'
    allowed_domains = ['www.douban.com']
    start_urls = ['https://www.douban.com/accounts/login']

    def start_requests(self):
        """重寫父類方法"""
        # 將請求參數封裝到字典
        data = {
            'source': 'index_nav',
            'form_email': '18xxxxxxx0',
            'form_password': 'hxxxxxxx'
        }
        for url in self.start_urls:
            yield scrapy.FormRequest(url=url, formdata=data, callback=self.parse)

    def parseBySecondPage(self, response):
        """針對我的主頁頁面數據進行解析操做"""
        fp = open('second.html', 'w', encoding='utf-8')
        fp.write(response.text)

        # 能夠對當前用戶的我的主頁數據進行指定解析操做
        # 若是服務器端能夠給咱們的請求返回一個cookie,第二次使用請求對象發起請求時,cookie就會自動攜帶到請求中

    def parse(self, response):
        # 對登陸成功後的頁面數據進行存儲
        # 這裏沒有在管道中處理,簡化操做直接保存在文件中
        fp = open('main.html', 'w', encoding='utf-8')
        fp.write(response.text)

        # 獲取當前用戶的我的主頁
        url = 'https://www.douban.com/people/186757832/'
        yield scrapy.Request(url=url, callback=self.parseBySecondPage)

一、重寫父類方法start_requests發起post請求

def start_requests(self):
    """重寫父類方法"""
    # 將請求參數封裝到字典
    data = {
        'source': 'index_nav',
        'form_email': '18xxxxxx0',
        'form_password': 'hxxxxxxx'
    }
    for url in self.start_urls:
        yield scrapy.FormRequest(url=url, formdata=data, callback=self.parse)

二、parse和parseBySecondPage方法兩次對我的主頁發起請求

def parseBySecondPage(self, response):
        """針對我的主頁頁面數據進行解析操做"""
        fp = open('second.html', 'w', encoding='utf-8')
        fp.write(response.text)

    def parse(self, response):
        # 對登陸成功後的頁面數據進行存儲
        fp = open('main.html', 'w', encoding='utf-8')
        fp.write(response.text)

        # 獲取當前用戶的我的主頁
        url = 'https://www.douban.com/people/186757832/'
        yield scrapy.Request(url=url, callback=self.parseBySecondPage)

  若是服務器端能夠給咱們的請求返回一個cookie,第二次使用請求對象發起請求時,cookie就會自動攜帶到請求中。
  查看mian.html和second.html文件,能夠發現兩次訪問結果相同,說明第二次發請求時攜帶了cookie。bash

3、Scrapy代理操做

一、本地ip獲取

  新建proxyPro工程,經過爬蟲在百度搜索ip,獲取本地ip地址。服務器

import scrapy

class ProxydemoSpider(scrapy.Spider):
    name = 'proxyDemo'
    # allowed_domains = ['www.baidu.com/s?wd=ip']
    start_urls = ['http://www.baidu.com/s?wd=ip']  # 百度搜索到本地ip

    def parse(self, response):
        fp = open('proxy.html', 'w', encoding='utf-8')
        fp.write(response.text)

  爬蟲文件編輯好後,修改settings.py文件,執行爬蟲:scrapy crawl proxyDemo --nolog;查看proxy.html內容以下所示:cookie

本地ip地址獲取

二、下載中間件(Downloader Middlewares)介紹

調度過程

  • 日常狀況:
    引擎調用start_requests方法,對列表中對應的列表元素進行請求,全部請求成功後,移交給引擎,引擎再將請求提交給調度器,這些請求都放置在調度器隊列當中,調度給 下載器,下載器拿到對應的請求去互聯網進行下載。
  • 代理操做:
    調度器將請求給下載器的時候,會穿過下載中間件,下載中間件就能夠對請求進行攔截,更換請求對應的ip,換爲其餘的代理IP。代理IP更換後將請求發給下載器,下載器用修改過ip的請求去互聯網去下載。
  • 下載中間件的做用:
    攔截調度器發給下載器的請求,將請求當中對應的IP進行更換,下載器拿到IP更換後的請求去互聯網進行數據的下載。

三、代理操做代碼實現

  在項目當前的源文件middlewares.py中,能夠看到類:ProxyproDownloadMiddleware,這是封裝好的下載中間件。其中process_request方法最爲重要,負責處理請求。
  在全網代理IP網站:http://www.goubanjia.com/,查找一條代理IP地址(39.137.69.10:8434)使用dom

(1)自定義下載中間件的類

  在middlewares.py中,自定義一個下載中間件的類,在類中實現process_request方法來處理中間件攔截到的請求。scrapy

from scrapy import signals

class MyProxy(object):
    # 自定義下載中間件
    def process_request(self, request, spider):
        # 將攔截的請求的請求ip更換
        request.meta["proxy"] = "http://39.137.69.10:8434"

注意:ide

  • 自定義類繼承object類;
  • 重寫process_request方法,必須包含父類的self、request、spider這三個參數;
  • 用request調出meta這個屬性,修改meta中'proxy'這個key對應的value值更換爲要修改的代理ip。

(2)修改settings.py使用自定義的中間件

  使用下載中間件,須要在配置文件中開啓下載中間件。

# Enable or disable downloader middlewares
# See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = {   # 開啓下載中間件
    # 'proxyPro.middlewares.ProxyproDownloaderMiddleware': 543,
    # 自定義下載中間件
    'proxyPro.middlewares.MyProxy': 543,   # 543爲優先級級別
}

(3)執行爬蟲查看百度搜索獲得的ip地址

$ scrapy crawl proxyDemo

查看得到的頁面信息:

美國Ip地址

相關文章
相關標籤/搜索