1. scrapy有三种方法模拟登陆

1.1直接携带cookies

1.2找url地址,发送post请求存储cookie

1.3找到对应的form表单,自动解析input标签,自动解析post请求的url地址,自动带上数据,自动发送请求

2. scrapy携带cookies直接获取需要登陆后的页面

2.1 应用场景

2.1.1cookie过期时间很长,常见于一些不规范的网站

2.1.2能在cookie过期之前把搜有的数据拿到

2.1.3配合其他程序使用,比如其使用selenium把登陆之后的cookie获取到保存到本地,scrapy发送请求之前先读取本地cookie

2.2 实现:重构scrapy的start_rquests方法

scrapy中start_urls是通过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_urls地址中的url是需要登录后才能访问的url地址,则需要重写start_request方法并在其中手动添加上cookie

2.3 携带cookies登陆

import scrapy

class ItSpider(scrapy.Spider):
name = 'it'
allowed_domains = ['enren.com']
start_urls = ['http://www.renren.com/260246846/newsfeed/photo'] def parse(self, response):
print("----parse----")
with open("renren2.html", "w") as f:
f.write(response.body.decode()) def start_requests(self): # 重构start_requests方法
# 这个cookies_str是抓包获取的
cookies_str = """anonymid=jxkbmqz1k8rnj7; _r01_=1; depovince=GW; ick_login=bf826d1f-53dc-4829-81e1-da6554509e97; first_login_flag=1; ln_uact=dong4716138@163.com; ln_hurl=http://hdn.xnimg.cn/photos/hdn521/20190703/0820/main_Rdy3_c9750000c97b1986.jpg; JSESSIONID=abcHmX81Tn80iaLs-yHWw; jebecookies=210f9dee-e58e-4cb5-a3f8-777b74969dd9|||||; _de=55D1995656E8B7574112FD057B0CD36E34DF20B0B3AA6FF7; p=51eebfa2d9baf41144b0bc8858e9061b6; t=1d75b874aa18d7b78cf616e523078e0f6; societyguester=1d75b874aa18d7b78cf616e523078e0f6; id=260246846; xnsid=de931535; ver=7.0; loginfrom=null; wp_fold=0""" # 抓包获取
# 将cookies_str转换为cookies_dict
cookies_dict = {i[:i.find('=')]: i[i.find('=')+1:] for i in cookies_str.split('; ')} print(">>>cookie>>>", cookies_dict)
for url in self.start_urls:
yield scrapy.Request(
url=url,
callback=self.parse,
cookies=cookies_dict
)

注意:

  1. scrapy中cookie不能够放在headers中,在构造请求的时候有专门的cookies参数,能够接受字典形式的cookie
  2. 在setting中设置ROBOTS协议、USER_AGENT

注意2:

既然start_urls列表中的url会经过start_requests方法进行处理,所以可以考虑如果在start_urls中的url默认需要用POST提交的话,可以考虑在start_requests方法中进行处理

注意3:

可以尝试使用scrapy的中间件携带cookie

middlewares.py:

import requests
import logging
import json
# 自定义微博请求的中间件
class WeiBoMiddleWare(object):
def __init__(self, cookies_pool_url):
self.logging = logging.getLogger("WeiBoMiddleWare")
self.cookies_pool_url = cookies_pool_url def get_random_cookies(self):
try:
response = requests.get(self.cookies_pool_url)
except Exception as e:
self.logging.info('Get Cookies failed: {}'.format(e))
else:
# 在中间件中,设置请求头携带的Cookies值,必须是一个字典,不能直接设置字符串。
cookies = json.loads(response.text)
self.logging.info('Get Cookies success: {}'.format(response.text))
return cookies @classmethod
def from_settings(cls, settings):
obj = cls(
cookies_pool_url=settings['WEIBO_COOKIES_URL']
)
return obj def process_request(self, request, spider):
request.cookies = self.get_random_cookies()
return None

settings.py:

# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Host': 'weibo.cn',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0',
}
DOWNLOADER_MIDDLEWARES = {
'weibospider.middlewares.WeiBoMiddleWare': 543,
} # 配置微博Cookie池的地址
WEIBO_COOKIES_URL = 'http://localhost:5000/weibo/random'
————————————————

3. scrapy.FormRequest发送post请求

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

yield scrapy.FormRequest(
"https://github.com/session",
formdata={
"authenticity_token":authenticity_token,
"utf8":utf8,
"commit":commit,
"login":"dong4716138@163.com",
"password":"xxxx"
},
callback=self.parse_login
)

3.2 使用scrapy.FormRequest()登陆github

3.2.1 思路分析

  1. 找到post的url地址:点击登录按钮进行抓包,然后定位url地址为https://github.com/session
  2. 找到请求体的规律:分析post请求的请求体,其中包含的参数均在前一次的响应中
  3. 否登录成功:通过请求个人主页,观察是否包含用户名

3.2.2 代码实现如下:

# -*- coding: utf-8 -*-
import scrapy
import re class GitSpider(scrapy.Spider):
name = 'git'
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() # 构造POST请求,传递给引擎
yield scrapy.FormRequest(
"https://github.com/session",
formdata={
"authenticity_token": authenticity_token,
"utf8": utf8,
"commit": commit,
"login": "993484988@qq.com", # 填写自己的GitHub账号
"password": "xxxxxxx", # 填写自己的GitHub密码
"webauthn - support": "supported"
},
callback=self.parse_login
) def parse_login(self, response):
ret = re.findall(r"dong138", response.text)
print(ret)

4. 小技巧

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

总结

  1. start_urls中的url地址是交给start_request处理的,如有必要,可以重写start_request函数
  2. 直接携带cookie登陆:cookie只能传递给cookies参数接收
  3. scrapy.FormRequest()发送post请求
 

scrapy 基础组件专题(十二):scrapy 模拟登录的更多相关文章

  1. scrapy 基础组件专题(二):下载中间件

    下载器中间件是介于Scrapy的request/response处理的钩子框架,是用于全局修改Scrapy request和response的一个轻量.底层的系统. 1.激活Downloader Mi ...

  2. scrapy 基础组件专题(十四):scrapy CookiesMiddleware源码

    一 Scrapy框架--cookie的获取/传递/本地保存 1. 完成模拟登陆2. 登陆成功后提取出cookie,然后保存到本地cookie.txt文件中3. 再次使用时从本地的cookie.txt中 ...

  3. scrapy 基础组件专题(八):scrapy-redis 框架分析

    scrapy-redis简介 scrapy-redis是scrapy框架基于redis数据库的组件,用于scrapy项目的分布式开发和部署. 有如下特征:  分布式爬取 您可以启动多个spider工 ...

  4. scrapy 基础组件专题(七):scrapy 调度器、调度器中间件、自定义调度器

    一.调度器 配置 SCHEDULER = 'scrapy.core.scheduler.Scheduler' #表示scrapy包下core文件夹scheduler文件Scheduler类# 可以通过 ...

  5. scrapy 基础组件专题(九):scrapy-redis 源码分析

    下面我们来看看,scrapy-redis的每一个源代码文件都实现了什么功能,最后如何实现分布式的爬虫系统: connection.py 连接得配置文件 defaults.py 默认得配置文件 dupe ...

  6. scrapy 基础组件专题(六):自定义命令

    写好自己的爬虫项目之后,可以自己定制爬虫运行的命令. 一.单爬虫 在项目的根目录下新建一个py文件,如命名为start.py,写入如下代码: from scrapy.cmdline import ex ...

  7. scrapy 基础组件专题(五):自定义扩展

    通过scrapy提供的扩展功能, 我们可以编写一些自定义的功能, 插入到scrapy的机制中 一.编写一个简单的扩展 我们现在编写一个扩展, 统计一共获取到的item的条数我们可以新建一个extens ...

  8. scrapy 基础组件专题(四):信号运用

    一.scrapy信号使用的简单实例 import scrapy from scrapy import signals from ccidcom.items import CcidcomItem cla ...

  9. scrapy 基础组件专题(三):爬虫中间件

    一.爬虫中间件简介 图 1-1 图 1-2 开始这一张之前需要先梳理一下这张图, 需要明白下载器中间件和爬虫中间件所在的位置 下载器中间件是在引擎(ENGINE)将请求推送给下载器(DOWNLOADE ...

随机推荐

  1. apt用法详解

    目录 1. 常规操作 2. apt-cache 3. 配置apt-get的缓存路径 4. 常用工具集 4.1. 开发工具 4.2. 系统辅助 1. 常规操作 更新仓库 sudo apt-get upd ...

  2. apt update 提示 Release file for http://… is not valid yet (invalid for another d..)

    由于在公司里需要使用代理上网,搞了好久,好不容易把 apt 整得可以访问外网了,结果在执行 spt update 时总是提示 Release file for http://- is not vali ...

  3. [noi.ac省选模拟赛]第10场题解集合

    题目 比赛界面. T1 不难想到,对于一个与\(k\)根棍子连接的轨道,我们可以将它拆分成\(k+1\)个点,表示这条轨道不同的\(k+1\)段. 那么,棍子就成为了点与点之间的边.可以发现,按照棍子 ...

  4. Codeforces Round #647 (Div. 2)

    Problem A https://codeforces.com/contest/1362/problem/A 判断x/y是不是2的k次方, 如果是 k/3 + (k%3)/2 + (k%3%2)即为 ...

  5. 面试问Redis集群,被虐的不行了......

    哨兵主要针对单节点故障无法自动恢复的解决方案,集群主要针对单节点容量.并发问题.线性可扩展性的解决方案.本文使用官方提供的redis cluster.文末有你们想要的设置ssh背景哦! 本文主要围绕如 ...

  6. docker部署dubbo怎么实现外部主机访问服务?

    dubbo在分布式项目中太常见了,docker也是现在热门的项目,然而docker的网络配置也是非常麻烦的一件事情,这里给大家介绍一下dubbo实现跨服务器访问服务配置 docker-compose. ...

  7. 傻瓜式教学--win10 + frp + rdpwrap + 阿里云服务器 --实现win10 多用户同时远程登录内网机

    概述: 使用win10 专业版 + frp + RDPwrap + 阿里云服务器 的组合实现win10 多用户同时远程登录内网机.使用frp 做内网穿透,将内网机的指定端口暴露在外网,通过ip+por ...

  8. Python初识函数

    Python初识函数 函数理论篇 什么是函数 在编程语言中的函数不同于数学中的函数.不管是数学上的函数还是编程语言中的函数都是为了完成特定的某一功能而诞生的,他们的区别在于: 1.数学中的函数当输入的 ...

  9. h5请求签名加密

    签名说明 签名对 url + method + 业务参数 进行统一签名,防止重放和篡改 客户端js对加密逻辑和appSecret进行混淆加密处理,增加破解难度 客户端本地存储appid 和 appSe ...

  10. SpringBoot中VO,DTO,DO,PO的概念、区别和用处

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/zhuguang10/article/de ...