關於scrapy框架中遇到需要登錄時的解決辦法

最近在工作中頻繁遇到需要登錄後才能抓取的數據,但也不是沒有解決辦法,以往解決辦法如下:

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': userAgent
}


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': userAgent
}


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)



 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章