日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Python3爬蟲模擬新浪微博登錄(2019-8-3)最新

系統 2069 0

目錄

  • Python3爬蟲模擬新浪微博登錄
    • 過程分析
    • 遇到的坑
    • 關于第一步,賬號和密碼加密
    • 登錄請求post數據包裝
    • 關于登錄后如跳轉到主頁面
    • 其他模塊
    • 執行結果

Python3爬蟲模擬新浪微博登錄

初學Python3小白一枚,若有錯誤請不吝賜教

過程分析

Python3爬蟲模擬新浪微博登錄(2019-8-3)最新_第1張圖片

整個過程 從填寫數據到跳轉到主頁一共經歷了七個步驟:
1.在登陸前,輸入賬號結束,失去輸入框焦點,瀏覽器會發送兩個請求,分別請求了登陸前加密密碼所需的servertime、nonce、pubkey(圖中對應3)
2.第二個ajax請求的是關于驗證碼的(圖中對應4、5)
3.這個是點擊登錄按鈕后,將加密后的數據post到服務器(圖中對應6)
4.服務器會返回一系列數據,(對應圖中的8),它包含了重定向的地址
5.多次頁面加載后,會接收到來自服務器的json數據包(對應圖中的19)在這
個數據包中包含了每個微博用戶特定的uniqueid
6.這是一個攜帶有相關用戶信息的script腳本(對應圖中的22)
7.經過一系列的跳轉后,最終跳轉到個人主頁面

遇到的坑

遇到的最嚴重的坑,就是驗證碼的啦
驗證碼的請求分析,著實耗費了大半天 。這是驗證碼請求的服務器地址:
https://login.sina.com.cn/cgi/pin.php?r=18674039&s=0&p=yf-c92f2edb50c21d4bcbfdc3fccfdb94c4c23f
其中分析后發現:
固定服務器url:https://login.sina.com.cn/cgi/pin.php?
攜帶的參數:r = 18674039,p = yf-c92f2edb50c21d4bcbfdc3fccfdb94c4c23f,s = 0
其中s和p是固定值,r是一串不固定變化的數字,在分析的過程中,我試圖尋找關于r的規律,最后實在沒辦法,我打算在Fiddler中測試一下,看看不加參數r是否能獲得,結果是可喜可賀的,確實獲得了。
事實上,在保證cookie一致的情況下,去請求驗證碼,也就是說和你本次的登錄保持在一個cookie中,可以主動的抓取驗證碼。

            
              
                # 獲取驗證碼
              
              
                def
              
              
                get_verificationcode
              
              
                (
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "開始請求獲取驗證碼..."
              
              
                )
              
              
    url 
              
                =
              
              
                "https://login.sina.com.cn/cgi/pin.php?s=0&p=yf-9f5e31626347e127bc21874aa9d6f4d745ca"
              
              
    request
              
                .
              
              urlretrieve
              
                (
              
              url
              
                =
              
              url
              
                ,
              
               filename
              
                =
              
              
                "./img/code.jpg"
              
              
                )
              
              
                print
              
              
                (
              
              
                "驗證碼獲取成功!"
              
              
                )
              
              
                return
              
              
                input
              
              
                (
              
              
                "請輸入驗證碼:"
              
              
                )
              
            
          

在應對驗證碼問題上,我這里采用的是半人工半自動的,將每次獲得的驗證碼存到當前目錄下的img文件中,人工查看和輸入驗證碼。

關于第一步,賬號和密碼加密

經分析在第二步發送登錄的post請求之前,瀏覽器會實現發一個請求,請求的響應信息如下:
Python3爬蟲模擬新浪微博登錄(2019-8-3)最新_第2張圖片
里邊攜帶的servertime、pubkey、nonce、rsakv等關鍵信息在后邊加密密碼和包裝post請求數據非常關鍵。關于如何得到這個分析以及整個爬蟲的結構也,參考了這篇博文:https://www.cnblogs.com/houkai/p/3488468.html.
以下是加密模塊encrypt.py的代碼

            
              
                import
              
               base64

              
                import
              
               binascii

              
                import
              
               rsa


              
                # 對用戶名加密
              
              
                def
              
              
                encryUsername
              
              
                (
              
              username
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "開始加密用戶名..."
              
              
                )
              
              
    text 
              
                =
              
              
                (
              
              base64
              
                .
              
              b64encode
              
                (
              
              username
              
                .
              
              encode
              
                (
              
              encoding
              
                =
              
              
                "utf-8"
              
              
                )
              
              
                )
              
              
                )
              
              
    text 
              
                =
              
               text
              
                .
              
              decode
              
                (
              
              
                )
              
              
                return
              
              
                str
              
              
                (
              
              text
              
                )
              
              
                .
              
              replace
              
                (
              
              
                "="
              
              
                ,
              
              
                ""
              
              
                )
              
              
                # 對密碼加密
              
              
                def
              
              
                encryPassword
              
              
                (
              
              password
              
                ,
              
              servertime
              
                ,
              
              nonce
              
                ,
              
              pubkey
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "開始加密密碼..."
              
              
                )
              
              
    rsaPublickey 
              
                =
              
              
                int
              
              
                (
              
              pubkey
              
                ,
              
              
                16
              
              
                )
              
              
    key 
              
                =
              
               rsa
              
                .
              
              PublicKey
              
                (
              
              rsaPublickey
              
                ,
              
              
                65537
              
              
                )
              
              
                # 創建公鑰
              
              
    message 
              
                =
              
              
                str
              
              
                (
              
              servertime
              
                )
              
              
                +
              
              
                '\t'
              
              
                +
              
              
                str
              
              
                (
              
              nonce
              
                )
              
              
                +
              
              
                '\n'
              
              
                +
              
              
                str
              
              
                (
              
              password
              
                )
              
              
                # 拼接明文js加密文件中得到
              
              
    message 
              
                =
              
              
                bytes
              
              
                (
              
              message
              
                ,
              
               encoding
              
                =
              
              
                "utf-8"
              
              
                )
              
              
    passwd 
              
                =
              
               rsa
              
                .
              
              encrypt
              
                (
              
              message
              
                ,
              
               key
              
                )
              
              
                # 加密
              
              
    passwd 
              
                =
              
               binascii
              
                .
              
              b2a_hex
              
                (
              
              passwd
              
                )
              
              
                # 將加密信息轉換為16進制。
              
              
                return
              
               passwd

            
          

登錄請求post數據包裝

在Chrome的開發者模式下,可以抓取相關參數信息

            
              
                # 組織post數據
              
              
                def
              
              
                get_postData
              
              
                (
              
              su
              
                ,
              
              password
              
                ,
              
              servertime
              
                ,
              
              nonce
              
                ,
              
              pubkey
              
                ,
              
              rsakv
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "開始組織post數據..."
              
              
                )
              
              
                # 密碼加密
              
              
    sp 
              
                =
              
               encrypt
              
                .
              
              encryPassword
              
                (
              
              password
              
                ,
              
               servertime
              
                ,
              
               nonce
              
                ,
              
               pubkey
              
                )
              
              
                # 驗證碼請求
              
              
    door 
              
                =
              
               get_verificationcode
              
                (
              
              
                )
              
              
                # 構造post請求參數
              
              
    data 
              
                =
              
              
                {
              
              
                "door"
              
              
                :
              
               door
              
                ,
              
              
                "entry"
              
              
                :
              
              
                "weibo"
              
              
                ,
              
              
                "gateway"
              
              
                :
              
              
                1
              
              
                ,
              
              
                "from"
              
              
                :
              
              
                ""
              
              
                ,
              
              
                "savestate"
              
              
                :
              
              
                7
              
              
                ,
              
              
                "su"
              
              
                :
              
               su
              
                ,
              
              
                "sp"
              
              
                :
              
               sp
              
                ,
              
              
                "servertime"
              
              
                :
              
               servertime
              
                ,
              
              
                "service"
              
              
                :
              
              
                "miniblog"
              
              
                ,
              
              
                "nonce"
              
              
                :
              
               nonce
              
                ,
              
              
                "rsakv"
              
              
                :
              
               rsakv
              
                ,
              
              
                "encoding"
              
              
                :
              
              
                "UTF-8"
              
              
                ,
              
              
                "domain"
              
              
                :
              
              
                "sina.com.cn"
              
              
                ,
              
              
                "returntype"
              
              
                :
              
              
                "META"
              
              
                ,
              
              
                "vsnf"
              
              
                :
              
              
                1
              
              
                ,
              
              
                "useticket"
              
              
                :
              
              
                1
              
              
                ,
              
              
                "pwencode"
              
              
                :
              
              
                "rsa2"
              
              
                ,
              
              
                "prelt"
              
              
                :
              
              
                372
              
              
                ,
              
              
                "qrcode_flag"
              
              
                :
              
              
                "false"
              
              
                ,
              
              
                "url"
              
              
                :
              
              
                "https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack"
              
              
                }
              
              
    data 
              
                =
              
               parse
              
                .
              
              urlencode
              
                (
              
              data
              
                )
              
              
                .
              
              encode
              
                (
              
              
                "utf-8"
              
              
                )
              
              
                return
              
               data

            
          

關于登錄后如跳轉到主頁面

這個過程參考了:https://www.cnblogs.com/woaixuexi9999/p/9404745.html
在模塊login.py中定義了一個類Login,其中的登錄方法代碼:

            
              
                def
              
              
                login
              
              
                (
              
              self
              
                )
              
              
                :
              
              
                # 第一步 獲得時間戳、公鑰、nonce等數據
              
              
        req 
              
                =
              
               request
              
                .
              
              Request
              
                (
              
              url
              
                =
              
              self
              
                .
              
              __preloginUrl
              
                ,
              
              headers
              
                =
              
              self
              
                .
              
              headers1
              
                ,
              
              method
              
                =
              
              
                "get"
              
              
                )
              
              
        response 
              
                =
              
               request
              
                .
              
              urlopen
              
                (
              
              req
              
                )
              
              
        text 
              
                =
              
               response
              
                .
              
              read
              
                (
              
              
                )
              
              
        servertime
              
                ,
              
               nonce
              
                ,
              
               pubkey
              
                ,
              
               rsakv 
              
                =
              
               dealdata
              
                .
              
              get_prelogin
              
                (
              
              text
              
                =
              
              text
              
                )
              
              
                # 第二步 向服務器發送post請求 登錄信息
              
              
        postdata 
              
                =
              
               dealdata
              
                .
              
              get_postData
              
                (
              
              self
              
                .
              
              __su
              
                ,
              
              self
              
                .
              
              __password
              
                ,
              
              servertime
              
                ,
              
              nonce
              
                ,
              
              pubkey
              
                ,
              
              rsakv
              
                )
              
              
        req 
              
                =
              
               request
              
                .
              
              Request
              
                (
              
              url
              
                =
              
              self
              
                .
              
              __loginUrl
              
                ,
              
               headers
              
                =
              
              self
              
                .
              
              __postheaders
              
                ,
              
               data
              
                =
              
              postdata
              
                ,
              
              method
              
                =
              
              
                "post"
              
              
                )
              
              
        response 
              
                =
              
               request
              
                .
              
              urlopen
              
                (
              
              req
              
                )
              
              
        text 
              
                =
              
               response
              
                .
              
              read
              
                (
              
              
                )
              
              
                # 第三步 解析登錄響應數據 獲取中間鏈接
              
              
        replaceUrl 
              
                =
              
               dealdata
              
                .
              
              get_replaceUrl
              
                (
              
              text
              
                =
              
              text
              
                )
              
              
                # 分析登錄結果
              
              
        result
              
                ,
              
              retcode
              
                ,
              
              reason 
              
                =
              
               dealdata
              
                .
              
              get_reason
              
                (
              
              replaceUrl
              
                )
              
              
                if
              
               result
              
                ==
              
              
                False
              
              
                :
              
              
                print
              
              
                (
              
              
                "登錄失敗!"
              
              
                )
              
              
                print
              
              
                (
              
              
                "原因"
              
              
                ,
              
              reason
              
                )
              
              
                return
              
              
                else
              
              
                :
              
              
                print
              
              
                (
              
              
                "登錄成功!"
              
              
                )
              
              
                print
              
              
                (
              
              
                "正在向個人主頁跳轉..."
              
              
                )
              
              
                # 第四步 加載中間鏈接 提取ticket
              
              
        response 
              
                =
              
               request
              
                .
              
              urlopen
              
                (
              
              replaceUrl
              
                )
              
              
        text 
              
                =
              
               response
              
                .
              
              read
              
                (
              
              
                )
              
              
        ticket 
              
                =
              
               dealdata
              
                .
              
              get_ticket
              
                (
              
              text
              
                =
              
              text
              
                )
              
              
                # 第五步 利用ticket組合關鍵部分構造網址 獲得攜帶uniqueid的json數據
              
              
        uniqueidUrl 
              
                =
              
               ticket 
              
                +
              
              
                "&callback=sinaSSOController.doCrossDomainCallBack&scriptId=ssoscript0&client=ssologin.js(v1.4.19)&_=1564805281285"
              
              
        response 
              
                =
              
               request
              
                .
              
              urlopen
              
                (
              
              uniqueidUrl
              
                )
              
              
        text 
              
                =
              
               response
              
                .
              
              read
              
                (
              
              
                )
              
              
        uniqueid 
              
                =
              
               dealdata
              
                .
              
              get_uniqueid
              
                (
              
              text
              
                )
              
              
                # 第六步 跳轉到主頁
              
              
                print
              
              
                (
              
              
                "進入個人主頁..."
              
              
                )
              
              
        homeUrl 
              
                =
              
              
                "https://weibo.com/u/"
              
              
                +
              
               uniqueid 
              
                +
              
              
                "/home"
              
              
        request
              
                .
              
              urlretrieve
              
                (
              
              homeUrl
              
                ,
              
              
                "./html/home.html"
              
              
                )
              
            
          

其他模塊

處理數據的dealdata.py模塊

Python3爬蟲模擬新浪微博登錄(2019-8-3)最新_第3張圖片
工程文件列表
Python3爬蟲模擬新浪微博登錄(2019-8-3)最新_第4張圖片
code.jpg是驗證碼
home.html是加載的主頁

執行結果

Python3爬蟲模擬新浪微博登錄(2019-8-3)最新_第5張圖片

初學Python,深感Python的強大。人生苦短,我用Python。
此程序僅供嘗試使用,不可商用。
轉載請注明出處:https://blog.csdn.net/Blz624613442/article/details/98368815


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 定兴县| 灵宝市| 江川县| 绥江县| 竹山县| 奉节县| 天长市| 汾西县| 崇明县| 阿拉善盟| 胶南市| 舒兰市| 汝城县| 邢台县| 朝阳市| 合水县| 嘉祥县| 全州县| 青阳县| 大石桥市| 西宁市| 固原市| 临夏市| 莱州市| 库尔勒市| 东阿县| 房产| 伊金霍洛旗| 上饶市| 通化县| 吉林市| 贵州省| 邻水| 镶黄旗| 海原县| 奉化市| 堆龙德庆县| 镇安县| 湖南省| 曲周县| 突泉县|