python爬蟲scrapy框架——人工識別登錄知乎倒立文字驗證碼和數字英文驗證碼(1)


原創文章,轉載請注明出處!

目前知乎使用了點擊圖中倒立文字的驗證碼:

 

用戶需要點擊圖中倒立的文字才能登錄。

這個給爬蟲帶來了一定難度,但並非無法解決,經過一天的耐心查詢,終於可以人工識別驗證碼並達到登錄成功狀態,下文將和大家一一道來。


 

我們學習爬蟲首先就要知道瀏覽器給服務器傳輸有什么字段(我用的是Safari瀏覽器進行演示,當然Chrome、Firefox都可以)

我們點擊了第一個和第二個文字:

右鍵審查元素-->點擊登錄 后可以看到:

從右面可以得到:報文發送的URL是:https://www/zhihu/com/login/phone_num

這不難理解,知乎的登錄是把手機和郵箱區分開來,我們用的是手機登錄,經過測試郵箱的URL是:https://www/zhihu/com/login/email,這里就不截圖了。

把右面的資源往下拉:

除了phone_num是用戶名,password是密碼,我們還看到了幾個重要信息:_xsrf、captcha、captcha_type

那么重點來了,這都分別是什么意思呢?經過反復查詢,直接把簡介明了的解釋給大家:

_xsrf:是“跨站請求偽造”(CSRF / XSRF)(Cross Site Request Forgery),這是知乎的一個安全協議,當你第一次訪問知乎主頁www.zhihu.com的時候,知乎會自動往你的瀏覽器發送一個_xsrf字段並且和你的主機綁定,之后的你每次訪問知乎服務器時,你的瀏覽器都會帶上這個字段,知乎發現你發送的_xsrf是我給你的_xsrf時才能有權訪問,如果_xsrf錯誤或者不填都無法訪問。順便一提,這是一個安全機制,基本所有的網站都會設置一個 XSRF/CSRF 的字段,防止黑客攻擊。

我們既然知道瀏覽器每次向知乎發送請求時都會帶上_xsrf字段,那么我們的爬蟲就必須要模擬瀏覽器訪問知乎首頁獲取這個 _xsrf 字段並在登錄時提交這個字段,才能登錄成功。

captcha:里的"img_size"字段是固定的,每次都是[200,44],應該就是圖片大小的意思。后面的"input_points"是你點擊驗證碼中倒立文字的坐標,由於驗證碼中七個文字位置是固定的,我們只要每個字都點一下再進行登錄,再審查元素來確定每個字的坐標就能模擬點擊了(是不是豁然開朗),這個步驟自行點擊來獲取坐標,我把我測試好的七個文字坐標依次拿出來:[22.796875,22],[42.796875,22],[63.796875,21],[84.796875,20],[107.796875,20],[129.796875,22],[150.796875,22]

captcha_type:這個字段就有意思了,其中有一個小技巧來切換成數字英文驗證碼。如果把它設置成 "cn" 就是倒立文字驗證碼,設置成 "en" 就是數字英文驗證碼,我沒就這里設置成"cn",數字英文驗證碼網上很多,大家可自行尋找。(經測試不填這個字段也是數字英文驗證碼)

到這里思路就很清晰了,我們知道了這三個重要信息,就知道如何讓爬蟲登錄知乎了,不多說直接上代碼:

import requests

try:
    import cookielib
except:
    import http.cookiejar as cookielib

import re
import time
import json


def get_xsrf():
    # 獲取xsrf code
    response = session.get('https://www.zhihu.com', headers=header)
    # print(response.text)
    match_obj = re.match('[\s\S]*name="_xsrf" value="(.*?)"', response.text)
    if match_obj:
        return match_obj.group(1)
    return ''


def get_captcha():
    # 驗證碼URL是按照時間戳的方式命名的
    captcha_url = 'https://www.zhihu.com/captcha.gif?r=%d&type=login&lang=cn' % (int(time.time() * 1000))
    response = session.get(captcha_url, headers=header)
    # 保存驗證碼到當前目錄
    with open('captcha.gif', 'wb') as f:
        f.write(response.content)
        f.close()

    # 自動打開剛獲取的驗證碼
    from PIL import Image
    try:
        img = Image.open('captcha.gif')
        img.show()
        img.close()
    except:
        pass

    captcha = {
        'img_size': [200, 44],
        'input_points': [],
    }
    points = [[22.796875, 22], [42.796875, 22], [63.796875, 21], [84.796875, 20], [107.796875, 20], [129.796875, 22],
              [150.796875, 22]]
    seq = input('請輸入倒立字的位置\n>')
    for i in seq:
        captcha['input_points'].append(points[int(i) - 1])
    return json.dumps(captcha)


def zhihu_login(account, password):
    # 知乎登錄
    if re.match('1\d{10}', account):
        print('手機號碼登錄')
        post_url = 'https://www.zhihu.com/login/phone_num'
        post_data = {
            'captcha_type': 'cn',
            '_xsrf': get_xsrf(),
            'phone_num': account,
            'password': password,
            'captcha': get_captcha(),
        }

        response_text = session.post(post_url, data=post_data, headers=header)
        response_text = json.loads(response_text.text)
        if 'msg' in response_text and response_text['msg'] == '登錄成功':
            print('登錄成功!')
        else:
            print('登錄失敗')


if __name__ == '__main__':
    agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8'
    header = {
        'HOST': 'www.zhihu.com',
        'Referer': 'https://www.zhihu.com',
        'User-agent': agent,
    }
    session = requests.session()
    zhihu_login('輸入登錄的手機號', '輸入登錄密碼')

 想必大家看代碼都能看的懂了,我再簡單說一嘴重要的

非常要注意的地方是:必須要用session來請求驗證碼再用session來提交報文,為什么不能用requests呢?一個session就是一個會話,如果用一個session訪問了一個網站,后面再拿着這個session再請求這個網站,它會把網站帶給我們的cookie或者說網站放到字段里面的session完全的給帶回去,這里面的cookie就非常重要,在我們訪問知乎的時候,不管我們有沒有登錄,服務器都可以往我們的header里面放一些值,我們用pycharm的debug來看一下session:

可以看到里面有很多cookie,獲取驗證碼時服務器給我們發的這些cookie,必須在登錄時再傳給知乎服務器才算認證成功。如果在登錄時用requests,它會再建立一次session,就無法把獲取驗證碼帶來的cookies傳給服務器,這樣固然認證失敗。

好了,大功告成!只要輸入第幾個文字是倒立的就行了,比如第二個和第四個文字是倒立的,輸入:24  按回車后就自動添加坐標,是不是很開心!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM