Python爬蟲之urllib模擬登錄及cookie的那點事

来源:https://www.cnblogs.com/bertwu/archive/2020/07/17/13334042.html
-Advertisement-
Play Games

在web sprider crawl過程中,許多網站都需要登錄後才能訪問,一般如果我們不用爬蟲框架的前提下,常規用的就兩個庫 ,urllib庫和requests庫,本文將用最基礎的urllib庫,以模擬登錄人人網為例,理清爬蟲過程中登錄訪問和cookie的思緒。 1.終極方案,也是最簡單粗暴最有效的 ...


在web  sprider crawl過程中,許多網站都需要登錄後才能訪問,一般如果我們不用爬蟲框架的前提下,常規用的就兩個庫 ,urllib庫和requests庫,本文將用最基礎的urllib庫,以模擬登錄人人網為例,理清爬蟲過程中登錄訪問和cookie的思緒。


 

1.終極方案,也是最簡單粗暴最有效的方式。直接手動登錄,提取cookie,下次訪問直接在請求頭攜帶cookie

       我們知道,網站辨別用戶身份和保持會話的常用方式就是cookie和session,用戶登錄成功,伺服器返回一些特定字元串保存在本地瀏覽器中(cookie),瀏覽器下次訪問會直接攜帶cookie,這樣伺服器就可以根據返回的cookie驗證訪問者身份。通常如果用瀏覽器正常訪問,這部分事情瀏覽器會幫我們去做。但是在程式模擬登  錄時候,攜帶cookie就需要手動攜帶了。話不多說,直接進入主題。

    

 

 

    打開人人網登錄界面,填入自己正確的用戶名和密碼,成功登陸進去。

 

 

 

 

其中紅色框的就是伺服器給你的cookie,你的cookie就是以這樣的形式在request請求頭中的。直接將其複製粘貼下來,放入代碼中。上程式:

 

"""
首先手動登錄人人網,然後獲取cookie
"""

from urllib.request import urlopen, Request

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    # 'Accept-Encoding': 'gzip, deflate',  這部分通常註釋掉,因為這部分是高訴伺服器,本地支持的壓縮類型,因為瀏覽器會自動幫我們解壓,但是在程式中,沒辦法解壓,所以請求頭就不攜帶了
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Connection': 'keep-alive',
    'Cookie': 'anonymid=kcpawuyd33irh2a;depovince=GW;r01_=1; JSESSIONID=abcGzDX6FRQNVfwdUETBnx;ick_login=6a732399-3adf-471b-af92-9bd68299d515; \
    taihe_bi_sdk_uid=e4c3ee72270319312dde3088eb04c0be; taihe_bi_sdk_sefssion=6722a32d96ebbf8fd565fc7cc7f8f789;ick=1048bb79-0d32-46ab-8a11-af0c7e4cfa51;first_login_flag=1; \
    ln_uact=17795796865;ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; ga=GA1.2.2124318841.1594975538;gid=GA1.2.506855365.1594975538; \
    wp_fold=0;jebecookies=3833d4fe-20b3-4ecf-9efc-df9aca93641e|||||;de=5C6d0B07AA3EB53E377A21F126C928EF0; p=d3ae1effe255d4e057ef37f5682ac4850;\
    t=ba23da27a155cc2b84a43307e83b37a70;societyguester=ba23da27a155cc2b84a4f3307e83b37a70;id=974774570;xnsid=a3c6bde2;ver=7.0;loginfrom=null
', 'Host': 'www.renren.com', 'Referer': 'http://www.renren.com/974774570/profile''Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Mobile Safari/537.36' } url = 'http://www.renren.com/974774570/profile' #個人主頁 request = Request(url=url, headers=headers) response = urlopen(request) print(response.read().decode())

   註釋:程式的headers 是一個字典,是通過登錄後抓包來的如下:

 

 

 

 

 

 

    其實通常我們只需要攜帶圖中的兩個參數,cookie和User-Agent,,某些get請求中,只需偽裝User_agent即可。但是我為什麼帶這麼多呢,那是因為,在有的網站你抓取的過程中,你其他參數都配置完美,但是總是抓取錯誤,那麼問題八九不離十齣現在headers中,始終記住我們是用程式模擬瀏覽器訪問伺服器,說明程式偽裝的還不夠完美。

 那麼這時候就要考慮headers中是否缺失了某些頭部信息。為了防止出錯,乾脆全盤端過來,反正你瀏覽器訪問的時候就是帶的這些請求頭參數。但是要註意,請求頭Accept-Encoding (程式中已經交代清楚)和 Content-Length(這是瀏覽器計算出的長度,程式模擬沒辦法計算,所以註釋掉)通常註釋掉。

 

 HTTP請求中的常用消息頭

  accept:瀏覽器通過這個頭告訴伺服器,它所支持的數據類型
  Accept-Charset: 瀏覽器通過這個頭告訴伺服器,它支持哪種字元集
  Accept-Encoding:瀏覽器通過這個頭告訴伺服器,支持的壓縮格式
  Accept-Language:瀏覽器通過這個頭告訴伺服器,它的語言環境
  Host:瀏覽器通過這個頭告訴伺服器,想訪問哪台主機
  If-Modified-Since: 瀏覽器通過這個頭告訴伺服器,緩存數據的時間
  Referer:瀏覽器通過這個頭告訴伺服器,客戶機是哪個頁面來的  防盜鏈
  Connection:瀏覽器通過這個頭告訴伺服器,請求完後是斷開鏈接還是何持鏈接

  Content-Length:瀏覽器通過這個頭告訴伺服器發出去的位元組長度

2. 模擬登錄,然後訪問主頁(在程式中我們不需要關心cookie是如何如何的,opener對象會自動幫我們處理,與之對應的是方式3,見下文)


 

 

 

      

 

 

 通過抓包如上圖,分析登錄post請求的地址和攜帶的參數

      

 

 

 直接上代碼:

"""
真正的模擬登錄是:發送post請求之後,保存cookie,之後訪問攜帶cookie
"""
# http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=2020652227884 通過這13位數,我們可以以男人的直覺,嗅出這是精確到毫秒的時間戳,那m我們給他生成就是
url = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp={}'  # 登錄地址
import time
from urllib.request import Request, urlopen, HTTPCookieProcessor, build_opener, ProxyHandler
from urllib.parse import urlencode
from http.cookiejar import CookieJar, MozillaCookieJar

# 1. 創建cookiejar對象,這一種方式不用手動保存cookie,後期直接調用同一個opener即可,因為cookie已經在opener對象中
cookiejar = CookieJar()

# 2.通過cookiejar創建一個handler
handler = HTTPCookieProcessor(cookiejar)
# handler1 = ProxyHandler({'http': '182.101.207.11:8080'})     # 選擇是否需要代理(自己設定代理)
# 3.根據handler創建一個opener
opener = build_opener(handler)  # build_opener以傳遞多個handler對象,如果需要代理,則將handler1也傳入
unique_time = int(time.time() * 1000)  # 生成時間戳

headers = {
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Mobile Safari/537.36'
}

data = {
    'email': '17795796865',
    'icode': '',
    'origURL': 'http://www.renren.com/home',
    'domain': 'renren.com',
    'key_id': '1',
    'captcha_type': 'web_login',
    # 此處密碼是經過目標網站加密,不能直接放置原生密碼,加密密碼可以用瀏覽器抓包獲取
    'password': '4af866303efsdf40a11d9f01e9677f3374bb957f905790b62a7eaa1accaf0a634764a1',
    'rkey': '1ad002b47d8446d446f8d76f5bb5ff66',
    'f': 'http%3A%2F%2Fwww.renren.com%2F974774570%2Fnewsfeed%2Fphoto'
}
# 4 創建request對象
request = Request(url=url.format(unique_time), headers=headers)
# 5.post方式提交登錄
respose = opener.open(request, data=urlencode(data).encode())
print(respose.read().decode())
print('*' * 50)

# get方式訪問個人主頁
get_url = 'http://www.renren.com/974774570/profile'
request = Request(url=get_url, headers=headers)
respose = opener.open(request)
print(respose.read().decode())

      註釋:data中的數,我們一個都不能少,因為post請求中,抓包可以看到,瀏覽器就帶的這麼多參數。至於參數是什麼意思,我們唯一能一眼看懂的就是email(用戶名)和password(密碼)。密碼是加密後的,一定不能寫原生密碼,加密後這一竄密碼可以用瀏覽器登錄抓包獲取。至於其他的參數,這就是爬蟲的難點,比如像大型的互聯網公司如淘寶,這裡的data參數動輒幾十個,要破解相當有難度,我們暫且不需要關註這些,但是通常的網站我們稍作分析大概就能猜出來這裡某個參數的意思,實在猜不出來,就原生不動的放著試著登錄。大不了登錄不進去我麽可以採取上面的終極方案啊。始終記住,爬蟲工程師,獲取到網頁提取數據才是你的重點。不要把精力耗費到破解form_data中的參數上。

3.手動將cookie保存到本地文件中,後續請求中直接讀取該cookie文件即可


可能有的人就有疑問了,方式2既然能模擬登錄成功,那為什麼還要手動保存在本地呢,豈不是多此一舉。凡事存在即合理。在爬蟲過程中,我們可以手動提取cookie,或者模擬登錄,但是在分散式爬蟲或者多台機器同時爬取時候,如果讓每台機器都要copy cookie,或者讓每台機器都登錄一遍,這不是明智的選擇,那麼只有事先將cookie保存在文件中,後續每台機器的程式從文件中讀取即可。

程式和方式2的程式很相似:

import time
from fake_useragent import UserAgent
from urllib.request import Request, urlopen, HTTPCookieProcessor, build_opener, ProxyHandler
from urllib.parse import urlencode
from http.cookiejar import CookieJar, MozillaCookieJar
from time import sleep

url = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp={}'


# 模擬登錄
def save_cookie():
    # 1. 創建cookiejar對象
    # cookiejar = CookieJar()  # 這一種不用保存文件中,後期直接用同一個opener對象調用就行
    cookiejar = MozillaCookieJar()  # 這種方式是將cookie保存文件中
    # 2.通過cookiejar創建一個handler
    handler = HTTPCookieProcessor(cookiejar)
    # handler1 = ProxyHandler({'http': '182.101.207.11:8080'})     # 選擇是否需要代理
    # 3.根據handler創建一個opener
    opener = build_opener(handler)  # 可以傳遞多個handler對象,如果需要代理,則將handler1也傳入
    unique_time = int(time.time() * 1000)  # 生成時間戳

    headers = {
        'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Mobile Safari/537.36'
    }

    data = {
        'email': '17795796865',
        'icode': '',
        'origURL': 'http://www.renren.com/home',
        'domain': 'renren.com',
        'key_id': '1',
        'captcha_type': 'web_login',
        # 此處密碼是經過目標網站加密,不能直接放置原生密碼,加密密碼可以用瀏覽器抓包獲取
        'password': '4af866303e40a11901e9677f3374bb957f905790b62a7eaa1accaf0a634764a1',
        'rkey': '1ad002b47d8446d446f8d76f5bb5ff66',
        'f': 'http%3A%2F%2Fwww.renren.com%2F974774570%2Fnewsfeed%2Fphoto'
    }

    request = Request(url=url.format(unique_time), headers=headers)
    respose = opener.open(request, data=urlencode(data).encode())
    # 創建保存可以序列化cookie的文件對象
    cookiejar.save('cookiejar.txt', ignore_discard=True, ignore_expires=True)
    print(respose.read().decode())
    print('*' * 50)


# 訪問個人主頁
def use_cookie():
    get_url = 'http://www.renren.com/974774570/profile'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Mobile Safari/537.36'
    }
    # 1. 創建cookiejar
    cookiejar = MozillaCookieJar()
    # 2.從本地載入cookie文件
    cookiejar.load('cookiejar.txt')
    # 3.創建handler對象
    handler = HTTPCookieProcessor(cookiejar)
    # 4.創建opener對象
    opener = build_opener(handler)
    # 5.創建request對象
    request = Request(url=get_url, headers=headers)
    # 6.發送請求
    respose = opener.open(request)
    print(respose.read().decode())


if __name__ == '__main__':
    save_cookie()
    sleep(2)
    use_cookie()

運行程式我們可以看到本地有個cookiejar.txt文件

 

 

總結


 

   不管以哪種方式,我們的終極目的是為了爬取數據,而不是花里胡哨的模擬登陸,如果模擬登陸過程中幾次嘗試失敗,那麼不妨可以直接放棄,直接以第一種方式即可。畢竟人生苦短!由於精力有限,此處就沒有涉及驗證碼,通常大多數網站登陸幾次失敗後就有驗證碼驗證。後續有機會再講。

 

 

 

 

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上篇筆記講到了聚合函數的實現並且帶大家看了聚合函數是如何註冊到ClickHouse之中的並被調用使用的。這篇筆記,筆者會續上上篇的內容,將剖析一把ClickHouse聚合流程的整體實現。 第二篇文章,我們來一起看看聚合流程的實現~~ 上車! 1.基礎知識的梳理 ClickHouse的實現介面 Blo ...
  • 數據字典是oracle存放有關資料庫信息的地方,幾乎所有的系統信息和對象信息都可在數據字典中進行查詢。數據字典是oracle資料庫系統的信息核心,它是一組提供有關資料庫信息的表和視圖的集合,這些表和視圖是只讀的。它是隨著資料庫的建立而建立的,當資料庫執行特定動作時數據字典也會自動更新。數據一覽與數據 ...
  • 目前CSDN,博客園,簡書同步發表中,更多精彩歡迎訪問我的gitee pages HDFS NN,2NN,DN及HDFS2.x新特性 NameNode和SecondaryNameNode(重點) NN和2NN工作機制 第一階段:NameNode啟動 第一次啟動NameNode格式化後,創建fsima ...
  • 排序查詢 * 語法:order by 子句 * order by 排序欄位1 排序方式1 , 排序欄位2 排序方式2... * 排序方式: * ASC:升序,預設的。 * DESC:降序。 * 註意: * 如果有多個排序條件,則當前邊的條件值一樣時,才會判斷第二條件。 聚合函數:將一列數據作為一個整 ...
  • 之前一個手機觸屏壞了,最近需要使用手機做一些操作;今天嘗試使用adb工具進行調試; 安卓開發者網站:https://developer.android.google.cn/ adb調試工具介紹:https://developer.android.google.cn/studio/command-li ...
  • 添加ksoap2-android-assembly-3.6.3-jar-with-dependencies.jar包 創建KsoapHelper類 public class KsoapHelper { public static int timeOut = 30000; public static ...
  • 組合模式 透明模式與安全模式 對組合的篩選遍歷 無論是在生活中還是項目中,我們經常會遇到具有“部分-整體”概念的對象,比如員工與團隊的關係,這就類似樹形結構,可能具有很多的嵌套層次和分支,把這種複雜性直接暴露給調用端是不合適的。 組合模式 藉助組合模式,可以將這類具有“部分-整體”的對象組合成樹形的 ...
  • 此項目為Springboot工作流版本 windows 風格,瀏覽器訪問操作使用,非桌面應用程式。 1.代碼生成器: [正反雙向](單表、主表、明細表、樹形表,快速開發利器) freemaker模版技術 ,0個代碼不用寫,生成完整的一個模塊,帶頁面、建表sql腳本、處理類、service等完整模塊 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...