Scrapy框架之代理和cookie

Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式。Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息。无论何时用户链接到服务器,Web 站点都可以访问 Cookie 信息cookie需要个人用户登录网站。
  场景需求:获取用户个人主页二级页面的页面数据。

一、Scrapy发起post请求

  要登录网站,因此必须发送post请求,如何实现发送post请求?
  场景需求:百度翻译中指定词条对应的翻译结果进行获取。

1、方法一:重写start_requests方法来发送post请求

  爬虫文件中的爬虫类继承到了Spider父类中的start_requests(self)这个方法,该方法就可以对start_urls列表中的url发起请求。
  该方法默认的实现,是对起始的url发起get请求,如果想发起post请求,则需要子类重写该方法。

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

2、方法二:利用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;"}]}

二、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)

1、重写父类方法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)

2、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。

三、Scrapy代理操作

1、本地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内容如下所示:

本地ip地址获取

2、下载中间件(Downloader Middlewares)介绍

调度过程

  • 平常情况:
    引擎调用start_requests方法,对列表中对应的列表元素进行请求,所有请求成功后,移交给引擎,引擎再将请求提交给调度器,这些请求都放置在调度器队列当中,调度给 下载器,下载器拿到对应的请求去互联网进行下载。
  • 代理操作:
    调度器将请求给下载器的时候,会穿过下载中间件,下载中间件就可以对请求进行拦截,更换请求对应的ip,换为其他的代理IP。代理IP更换后将请求发给下载器,下载器用修改过ip的请求去互联网去下载。
  • 下载中间件的作用:
    拦截调度器发给下载器的请求,将请求当中对应的IP进行更换,下载器拿到IP更换后的请求去互联网进行数据的下载。

3、代理操作代码实现

  在项目当前的源文件middlewares.py中,可以看到类:ProxyproDownloadMiddleware,这是封装好的下载中间件。其中process_request方法最为重要,负责处理请求。
  在全网代理IP网站:http://www.goubanjia.com/,查找一条代理IP地址(39.137.69.10:8434)使用。

(1)自定义下载中间件的类

  在middlewares.py中,自定义一个下载中间件的类,在类中实现process_request方法来处理中间件拦截到的请求。

from scrapy import signals

class MyProxy(object):
    # 自定义下载中间件
    def process_request(self, request, spider):
        # 将拦截的请求的请求ip更换
        request.meta["proxy"] = "http://39.137.69.10:8434" 

注意:

  • 自定义类继承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地址

posted @ 2018-12-02 23:53  休耕  阅读(513)  评论(0编辑  收藏  举报