scrapy模拟登陆

1、回顾之前的模拟登陆的方法

1.1 requests模块是如何实现模拟登陆的?
  1. 直接携带cookies请求页面

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

1.2 selenium是如何模拟登陆的?
  1. 找到对应的input标签,输入文本点击登陆

1.3 scrapy有二种方法模拟登陆
  1. 直接携带cookies

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

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

2.1 应用场景
  1. cookie过期时间很长,常见于一些不规范的网站

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

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

2.2 通过修改settings中DEFAULT_REQUEST_HEADERS携带cookie

settings.py

DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
  'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
  'Cookie': 'ASP.NET_SessionId=n4lwamv5eohaqcorfi3dvzcv; xiaohua_visitfunny=103174; xiaohua_web_userid=120326; xiaohua_web_userkey=r2sYazfFMt/rxUn8LJDmUYetwR2qsFCHIaNt7+Zpsscpp1p6zicW4w=='
}

注意:需要打开COOKIES_ENABLED,否则上面设定的cookie将不起作用

# Disable cookies (enabled by default)
COOKIES_ENABLED = False

局限性:

当前设定方式虽然可以实现携带cookie保持登录,但是无法获取到新cookie,也就是当前cookie一直是固定的

如果cookie是经常性变化,那么当前不适用

2.3 实现:重构scrapy的start_rquests方法

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

settings.py

import scrapy
​
​
class DengluSpider(scrapy.Spider):
    name = 'denglu'
    # allowed_domains = ['https://user.17k.com/ck/user/mine/readList?page=1']
    start_urls = ['https://user.17k.com/ck/user/mine/readList?page=1&appKey=2406394919']
​
    def start_requests(self):
        cookies = 'GUID=796e4a09-ba11-4ecb-9cf6-aad19169267d; Hm_lvt_9793f42b498361373512340937deb2a0=1660545196; c_channel=0; c_csc=web; accessToken=avatarUrl%3Dhttps%253A%252F%252Fcdn.static.17k.com%252Fuser%252Favatar%252F18%252F98%252F90%252F96139098.jpg-88x88%253Fv%253D1650527904000%26id%3D96139098%26nickname%3D%25E4%25B9%25A6%25E5%258F%258BqYx51ZhI1%26e%3D1677033668%26s%3D8e116a403df502ab; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2296139098%22%2C%22%24device_id%22%3A%22181d13acb2c3bd-011f19b55b75a8-1c525635-1296000-181d13acb2d5fb%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%2C%22first_id%22%3A%22796e4a09-ba11-4ecb-9cf6-aad19169267d%22%7D; Hm_lpvt_9793f42b498361373512340937deb2a0=1661483362'
        cookie_dic = {}
        for i in cookies.split(';'):
            v = i.split('=')
            cookie_dic[v[0]] = v[1]
        # {i.split('=')[0]:i.split('=')[1] for i in cookies_str.split('; ')}   # 简写
        for url in self.start_urls:
            yield scrapy.Request(url, cookies=cookie_dic)
​
​
    def parse(self, response):
        print(response.text)
注意:
  1. scrapy中cookie不能够放在headers中,在构造请求的时候有专门的cookies参数,能够接受字典形式的coookie

  2. 在setting中设置ROBOTS协议、USER_AGENT

3、scrapy.FormRequest发送post请求

我们知道可以通过scrapy.Request()指定method、body参数来发送post请求;那么也可以使用scrapy.FormRequest()来发送post请求

3.1 scrapy.FormRequest()的使用

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

login_url = 'https://passport.17k.com/ck/user/login'      
yield scrapy.FormRequest(
            url=login_url, 
            formdata={'loginName': '17346570232', 'password': 'xlg17346570232'}, 
            callback=self.do_login
)
3.2 使用scrapy.FormRequest()登陆
3.2.1 思路分析
  1. 找到post的url地址:点击登录按钮进行抓包,然后定位url地址为https://user.17k.com/ck/user/mine/readList?page=1&appKey=2406394919

  2. 找到请求体的规律:分析post请求的请求体,其中包含的参数均在前一次的响应中

  3. 否登录成功:通过请求个人主页,观察是否包含用户名

3.2.2 代码实现如下:
import scrapy
​
​
class DengluSpider(scrapy.Spider):
    name = 'denglu'
    # allowed_domains = ['17k.com']
    start_urls = ['https://user.17k.com/ck/user/mine/readList?page=1&appKey=2406394919']
​
    def start_requests(self):
        '''
        请求登陆的账号和密码
        '''
        login_url = 'https://passport.17k.com/ck/user/login'
        # 使用request进行请求
        # yield scrapy.Request(url=login_url, body='loginName=17346570232&password=xlg17346570232', callback=self.do_login, method='POST')
        # 使用Request子类FormRequest进行请求  自动为post请求
        yield scrapy.FormRequest(
            url=login_url,
            formdata={'loginName': '17346570232', 'password': 'xlg17346570232'},
            callback=self.do_login
        )
​
    def do_login(self, response):
        '''
        登陆成功后调用parse进行处理
        cookie中间件会帮我们自动处理携带cookie
        '''
        for url in self.start_urls:
            yield scrapy.Request(url=url, callback=self.parse)
​
    def parse(self, response, **kwargs):
        print(response.text)

总结

  1. start_urls中的url地址是交给start_request处理的,如有必要,可以重写start_request函数

  2. 直接携带cookie登陆:cookie只能传递给cookies参数接收

  3. scrapy.FormRequest()发送post请求

 

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A:使用scrapy模拟登陆大众点评网的步骤如下: 1. 在settings.py中添加COOKIES_ENABLED=True,开启cookies支持; 2. 在spider中编写start_requests方法,发送GET请求到大众点评的登录页面,获取登录页面的cookie; 3. 编写parse方法,解析登录页面的源代码,提取出登录时需要的参数、加密token等信息; 4. 编写一个登录方法,使用加密token和传递用户名和密码设置POST请求,将用户凭证提交到登录页面; 5. 再次编写parse方法,使用selenium打开登录页面,成功登录后,提取响应页面的cookie; 6. 在后续的请求中使用该cookie,以保持用户的登录状态。 具体实现代码如下: ```python import scrapy from scrapy.http import FormRequest from selenium import webdriver class DianPing(scrapy.Spider): name = 'dianping' allowed_domains = ['www.dianping.com'] start_urls = ['https://account.dianping.com/login'] def start_requests(self): yield scrapy.Request(url=self.start_urls[0], callback=self.parse, meta={ 'splash': { 'endpoint': 'render.html', 'args': {'wait': 0.5}, }, 'selenium': True }) def parse(self, response): # 获取cookie cookie = response.headers.getlist('Set-Cookie') cookie = [c.decode('utf-8').split(';')[0] for c in cookie] cookie = '; '.join(cookie) # 获取加密token token = response.css('input[name="token"]::attr(value)').extract_first() # 提交登录请求 yield FormRequest.from_response(response, formdata={ 'account': 'your_username', 'password': 'your_password', 'token': token, 'redir': 'https://www.dianping.com', 'rememberMe': 'true', }, headers={ 'Cookie': cookie, }, callback=self.after_login, meta={ 'splash': { 'endpoint': 'render.html', 'args': {'wait': 0.5}, }, 'selenium': True }) def after_login(self, response): # 使用selenium打开登录页面,获取cookie if '登录' not in response.body.decode('utf-8'): driver = response.meta['driver'] driver.get(response.url) cookies = driver.get_cookies() cookie_dict = {} for cookie in cookies: cookie_dict[cookie['name']] = cookie['value'] yield scrapy.Request( url='https://www.dianping.com/', cookies=cookie_dict, callback=self.parse_homepage, meta={ 'splash': { 'endpoint': 'render.html', 'args': {'wait': 0.5}, } } ) def parse_homepage(self, response): print(response.body) ``` 上述代码中,我们通过在start_requests的meta中添加了splash和selenium参数,使得start_requests方法使用splash和selenium的渲染能力来处理请求。在parse方法中,我们获取了登录页面的cookie和加密token,并设置了POST请求,将用户凭证提交到登录页面。在after_login方法中,我们使用selenium打开登录页面,并在parse_homepage方法中解析响应页面的源代码。最后,在后续的请求中使用获取到的cookie即可保持用户的登录状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值