下载中间件和模拟登陆

本文详细介绍了Scrapy框架中下载中间件的使用方法,包括如何实现随机User-Agent和代理,以及如何通过携带Cookie和发送POST请求来模拟登录。通过具体案例,如人人网和GitHub的模拟登录,展示了Scrapy在处理复杂网页登录流程中的灵活性。

目标

  1. 掌握常见的下载中间件的编写方式
  2. 掌握模拟登陆的思路
  3. 掌握scrapy中模拟登陆的三种方式

1 scrapy中下载中间件的使用

  1. 使用方法:

    编写一个Downloader Middlewares和我们编写一个pipeline一样,定义一个类,然后在setting中开启

  2. Downloader Middlewares默认的方法:

    • process_request(self, request, spider):

      • 当每个request通过下载中间件时,该方法被调用。
      • 返回None值:继续请求
      • 返回Response对象:不在请求,把response返回给引擎
      • 返回Request对象:把request对象交给调度器进行后续的请求
    • process_response(self, request, response, spider):

       - 当下载器完成http请求,传递响应给引擎的时候调用
       - 返回Resposne:交给process_response来处理
       - 返回Request对象:交给调取器继续请求
      
  3. 定义实现随机User-Agent的下载中间件

     class UserAgentMiddleware(object):
         def process_request(self,request,spider):
             agent = random.choice(agents)
             request.headers['User-Agent'] = agent
    
  4. 定义实现随机使用代理的下载中间件

     class ProxyMiddleware(object):
         def process_request(self,request,spider):
             proxy = random.choice(proxies)
             request.meta['proxy'] = proxy
    

    User-Agent池在这里

    USER_AGENTS = [ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)", "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)", "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 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)", "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0", "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5" ]

2 使用scrapy进行模拟登陆

2.1 回顾之前的模拟登陆的方法

  1. requests是如何模拟登陆的?

    1. 直接携带cookies请求页面
    2. 找接口发送post请求存储cookie
  2. selenium是如何模拟登陆的?

    1. 找到对应的input标签,输入文字点击登录

scrapy来说,有两个方法模拟登陆:

1、直接携带cookie
2、找到发送post请求的url地址,带上信息,发送请求

2.2 scrapy携带cookie进行模拟登陆

  1. 携带cookie进行模拟登陆应用场景:

    1. cookie过期时间很长,常见于一些不规范的网站
    2. 能在cookie过期之前把搜有的数据拿到
    3. 配合其他程序使用,比如其使用selenium把登陆之后的cookie获取到保存到本地,scrapy发送请求之前先读取本地cookie
  2. scrapy的start_requests方法的学习

    scrapy中start_url是通过start_requests来进行处理的,其实现代码如下

     def start_requests(self):
         cls = self.__class__
         if method_is_overridden(cls, Spider, 'make_requests_from_url'):
             warnings.warn(
                 "Spider.make_requests_from_url method is deprecated; it "
                 "won't be called in future Scrapy releases. Please "
                 "override Spider.start_requests method instead (see %s.%s)." % (
                     cls.__module__, cls.__name__
                 ),
             )
             for url in self.start_urls:
                 yield self.make_requests_from_url(url)
         else:
             for url in self.start_urls:
                 yield Request(url, dont_filter=True)
    

    所以对应的,如果start_url地址中的url是需要登录后才能访问的url地址,则需要重写start_request方法并在其中手动添加上cookie

  3. 实现携带cookie登录人人网

注意:scrapy中cookie不能够放在headers中,在构造请求的时候有专门的cookies参数,能够接受字典形式的coookie

import scrapy
import re

class RenrenSpider(scrapy.Spider):
    name = 'renren'
    allowed_domains = ['renren.com']
    start_urls = ['http://www.renren.com/941954027/profile']

    def start_requests(self):
        cookie_str = "cookie_str"
        cookie_dict = {i.split("=")[0]:i.split("=")[1] for i in cookie_str.split("; ")}
        yield scrapy.Request(
            self.start_urls[0],
            callback=self.parse,
            cookies=cookie_dict,
            # headers={"Cookie":cookie_str}
        )

    def parse(self, response):
        ret = re.findall("新用户287",response.text)
        print(ret)
        yield scrapy.Request(
            "http://www.renren.com/941954027/profile?v=info_timeline",
            callback=self.parse_detail
        )

    def parse_detail(self,response):
        ret = re.findall("新用户287",response.text)
        print(ret)
  1. 在settings中开启cookie_debug

    在settings.py中通过设置COOKIES_DEBUG=TRUE 能够在终端看到cookie的传递传递过程

2.3 scrapy发送post请求

  1. scrapy中发送post请求的方法 通过scrapy.FormRequest能够发送post请求,同时需要添加fromdata参数作为请求体,以及callback

     yield scrapy.FormRequest(
                 "https://github.com/session",
                 formdata={
                     "authenticity_token":authenticity_token,
                     "utf8":utf8,
                     "commit":commit,
                     "login":"noobpythoner",
                     "password":"zhoudawei123"
                 },
                 callback=self.parse_login
             )
    
  2. 使用scrapy模拟登陆github

    思路分析

    1. 找到post的url地址

      点击登录按钮进行抓包,然后定位url地址为https://github.com/session

    2. 找到请求体的规律

      分析post请求的请求体,其中包含的参数均在前一次的响应中

    3. 验证是否登录成功

      通过请求个人主页,观察是否包含用户名

      代码实现如下:

      #spider/github.py
      # -*- coding: utf-8 -*-
      import scrapy
      import re
      
      class GithubSpider(scrapy.Spider):
       name = 'github'
       allowed_domains = ['github.com']
       start_urls = ['https://github.com/login']
      
       def parse(self, response):
           authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()
           utf8 = response.xpath("//input[@name='utf8']/@value").extract_first()
           commit = response.xpath("//input[@name='commit']/@value").extract_first()
      
           yield scrapy.FormRequest(
               "https://github.com/session",
               formdata={
                   "authenticity_token":authenticity_token,
                   "utf8":utf8,
                   "commit":commit,
                   "login":"noobpythoner",
                   "password":"***"
               },
               callback=self.parse_login
           )
      
       def parse_login(self,response):
           ret = re.findall("noobpythoner",response.text,re.I)
           print(ret)
      

2.4 scrapy进行表单提交

  1. 方法介绍

    scrapy中具有一个方法:scrapy.Formrequest.from_response能够自动的从响应中寻找form表单,然后把formdata中的数据提交到action对应的url地址中

    使用实例如下

      def parse(self, response):
         yield scrapy.FormRequest.from_response(
             response,#自动的从中寻找action对应的url地址
             formdata={
                 "login":"noobpythoner",
                 "password":"***"
             },
             callback = self.parse_login
         )
    
  2. 使用scrapy.Formrequest.from_response进行模拟登陆github

Scrapy是一个强大的Python爬虫框架,用于高效地抓取网站数据。如果你需要模拟登录某个网站,Scrapy可以配合第三方库如Requests或Selenium来完成这个过程。以下是基本步骤: 1. 安装依赖:首先,你需要安装`scrapy`、`requests`(默认支持HTTP请求)`selenium`(如果目标网站有JavaScript验证)。 ```bash pip install scrapy requests selenium (如果需要) ``` 2. 创建Scrapy项目:使用`scrapy startproject your_project_name`命令创建一个新的Scrapy项目。 3. 导入必要的模块:在`settings.py`文件中添加对Selenium的支持,并设置一个中间件处理登录,例如: ```python DOWNLOADER_MIDDLEWARES = { 'your_project.middlewares.SeleniumMiddleware': 543, } ``` 4. 编写中间件(Middlewares):创建`middlewares/SeleniumMiddleware.py`文件,这里通常会使用`webdriver_manager`来管理浏览器驱动,然后初始化Selenium实例: ```python from scrapy import signals from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager class SeleniumMiddleware: def __init__(self): self.driver = webdriver.Chrome(ChromeDriverManager().install()) @classmethod def from_crawler(cls, crawler): middleware = cls() crawler.signals.connect(middleware.spider_opened, signal=signals.spider_opened) return middleware def spider_opened(self, spider): # 开启浏览器并导航到登录页面 self.driver.get(spider.login_url) def process_request(self, request, spider): if spider.is_login_required and 'login_form_data' in request.meta: # 提交表单数据,模拟登录 form_data = request.meta['login_form_data'] self.driver.find_element_by_name(form_data['username_field']).send_keys(form_data['username']) self.driver.find_element_by_name(form_data['password_field']).send_keys(form_data['password']) login_button = self.driver.find_element_by_css_selector(form_data['submit_button']) login_button.click() # 如果需要保持登录状态,可以在每个后续请求前检查cookie等信息 # ... return request ``` 5. 使用中间件:在Scrapy项目的spiders目录下,编写一个spider,将登录需求作为元数据传递给中间件: ```python class LoginSpider(scrapy.Spider): name = "login_spider" allowed_domains = ["example.com"] start_urls = ['http://example.com/login'] def is_login_required(self): return True def parse(self, response): # 登录成功后的解析逻辑 ... ``` 6. 设置登录数据启动爬虫:在运行spider之前,指定登录表单的数据(用户名、密码、提交按钮等),然后通过`scrapy crawl`命令启动。 ```bash scrapy crawl login_spider -a login_form_data={"username_field": "username", "password_field": "password", "submit_button": ".btn-login"} ``` 注意:并非所有网站都支持直接模拟登录,某些网站可能需要验证码、OAuth授权等方式。此外,频繁的模拟登录可能会触发反爬机制或违反服务条款,因此在实际操作时需谨慎。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值