关于scrapy框架中遇到需要登录时的解决办法

19 篇文章 0 订阅
8 篇文章 0 订阅

最近在工作中频繁遇到需要登录后才能抓取的数据,但也不是没有解决办法,以往解决办法如下:

A.  现在浏览器里登录,然后把登录后的cookie粘贴到代码中去请求,这样就相当与利用cookie"伪造"了一个分身,从而跳过登录验证。

这样往往可以解决大部分需求,但是遇到需要crontab定时爬取就显得鸡肋。cookies是有生存时间的,一旦cookies死掉那么服务器上正在跑的代码也会崩溃掉,如果还是用方法A的话,就需要手动的再去粘贴一个新的cookies。但是这对于一个程序员来说简直是不能忍,一个不能自动化运行的代码不是一个成熟的代码(对代码说的话:孩子,你已经长大了,是时候学会自己粘cookie了~.~)

基于以上问题,结合自己所学 得出plan B:

先用requests库去请求登录地址,得到response对象,然后调用response对象的 .cookies()方法 得到cookie,然后把这个cookie带入A,然后问题解决。

# -*- coding: utf-8 -*-

import requests

userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
header = {
    'Referer': 'https://account.wxb.com/from=https%3A%2F%2Fdata.wxb.com%2FrankArticle%3Fcate%3D3%26page%3D1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
}


def get_cookie():
    #登录时所请求的url(如果找不到此接口,先在浏览器中打开登录界面,输入一个错的账户名密码,点击登录,然后再开发者选项中就可以找到。
    #为什么要输入错的呢?因为如果正确的账户名密码点击登录会立刻进行重定向,就找不到这个接口了)
    postUrl = "https://account.wxb.com/login?from=https%3A%2F%2Fdata.wxb.com%2FrankArticle%3Fcate%3D3%26page%3D1"

    #模拟登录时带的帐户名,密码
    postData = {
        "email": "177*****043",
        "password": "weixiaobao123",
    }

    #发送请求,得到响应体
    response=requests.post(postUrl, data=postData, headers=header,verify=False)
    
    #返回cookie
    return response.cookies()

调用此方法便可返回登录后的cookie  注意:这个cookie是个RequestCookieJar的实例,而不是我们通常见到的字典类型。这也是这个办法用起来麻烦的地方

重点来了,plan C:

B中使用了response对象来返回cookie,然后每次用时需要再次设置cookies,但这样做起来显得很繁琐,下面介绍一个更简单的解决办法。

其实解决这个问题的主要方法就是维持同一个会话,也就是相当于打开一个新的浏览器选项卡而不是新开一个浏览器。但是我又不想每次设置cookies, 那该怎么办呢?这时候就有了新的利器 Session对象。
           利用它,我们可以方便地维护一一个会话,而且不用担心cookies的问题,它会帮我们自动处理好。如下:

# -*- coding: utf-8 -*-

import requests, json

#注意:此get_heager方法是自己写的一个转换headers的方法。从网页上复制下来的headers是字符串型,而发送请求的headers是字典类型,为避
#免每次手动改,就索性写了个方法自动转换,返回字典型(懒果然是驱动进步的源泉啊 ~ ^.^)最后会送上。
from header import get_header

userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
header = {
    'Referer': 'https://account.wxb.com/?from=https%3A%2F%2Fdata.wxb.com%2FrankArticle%3Fcate%3D3%26page%3D1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
}


def get_session():

    postUrl = "https://account.wxb.com/login?from=https%3A%2F%2Fdata.wxb.com%2FrankArticle%3Fcate%3D3%26page%3D1"
    postData = {
        "email": "177*****043",
        "password": "weixiaobao123",
    }
    
    #创建session对象
    session = requests.session()
    #使用Session对象发送登录请求,之后cookies就已经保存在Session对象中了
    session.post(postUrl, data=postData, headers=header,verify=False)

    header_str = '''Accept: application/json, text/plain, */*
                        Accept-Encoding: gzip, deflate, br
                        Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
                        Connection: keep-alive
                        Host: data.wxb.com
                        Referer: https://data.wxb.com/rankArticle?cate=-1&page=6
                        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
                        X-Requested-With: XMLHttpRequest
                    '''
    #使用get_header()方法将字符串型转换为可以使用的字典型
    header1 = get_header(header_str)
    #返回携带cookies的Session对象和请求头
    return session, header1

返回Session对象以后,就可以使用该对象访问想要访问的资源了。这是框架里的一部分调用了此方法:

    def parse(self, response):
        # 得到模拟登陆后的session对象和请求头
        session, header = get_session()
        for i in range(10):
            url = 'https://data.wxb.com/rank/article?category=-1&page=' + str(i + 1) + '&pageSize=20&type=2&order='
            res = session.get(url, headers=header, verify=False)
            #将得到的数据序列化
            lis = json.loads(res.text)
            print(res.text)
            for j in lis['data']:
                item = WeixiaobaoItem()
                read_num = j['read_num']
                # print(read_num)
                if read_num == u'10万+':
                    title = j['title']
                    account = j['account']
                    index_scores = j['index_scores']
                    url = j['url']
                    like_num = j['like_num']

                    item['title'] = title
                    item['account'] = account
                    item['index_scores'] = index_scores
                    item['read_num'] = read_num
                    item['like_num'] = like_num
                    item['url'] = url

                    yield item

最后,把headres转换方法以及cookies转换方法放在这里:

# -*- coding: utf-8 -*-
def get_header(str):
    result = {}  # 初始化返回结果
    str_new = str.replace(': ', ':').replace('    ', '')  # 第一步,将里面的冒号空格转换为冒号,然后消掉tab
    str_list = str_new.split('\n')  # 第二部,将字符串按行分割,可能会出现列表的第一个元素和最后一个元素为空字符串的情况
    for i in str_list:
        if i:  # 做个筛选,过滤掉空字符串
            # 此时的i是字符串,现在要将它转为键值对
            temp = i.split(':')
            key = temp[0]
            value = ':'.join(temp[1:])
            result[key] = value  # 将键值对赋值给字典
    return result


def get_cookie(str):
    result = {}
    str_new = str.replace(' ', '')
    str_list = str_new.split(';')
    for i in str_list:
        if i:
            temp = i.split('=')
            key = temp[0]
            value = ':'.join(temp[1:])
            result[key] = value  # 将键值对赋值给字典
    return result

使用方法:

header_str='''Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Host: www.baidu.com
Referer: https://www.baidu.com/s?ie=UTF-8&wd=linux%20crontab
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'''

# 返回字典
header = get_header(header_str)

cookie_str='''BIDUPSID=64C64E96A29EFCD95DBC15E7B3476840; PSTM=1527935009; BAIDUID=C5854F8A373874C0FDC858FB42BB5A3E:FG=1; __cfduid=db02ba44dd85fc27f9e77e1206c5aa4251539954648; BDUSS=hYc3hpUG1MOS16RS1TNlBTSDdSS2RwWUN1dzd5bWo2NWFrRHFOaGFvY1ZsfnRiQVFBQUFBJCQAAAAAAAAAAAEAAAC6YFstwqbKwMP0NTIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUK1FsVCtRbNU; BD_UPN=12314753; MCITY=-131%3A; BAIDUCUID=gavI8gaB28YEPvaAj8SA8juf2i0_i289_uvStguq2ii9avt_gavct_uH-t_OP2tDA; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; H_PS_PSSID=26524_1454_25810_21101_28329_28414; BD_HOME=1; delPer=0; BD_CK_SAM=1; PSINO=2; sugstore=1'''

# 返回字典
cookie= get_cookie(cookie_str)



 

 

 

 

 

 

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值