python爬蟲:兩種方法模擬登錄博客園


第一方法用第三方庫(requests):參考http://www.mamicode.com/info-detail-1839685.html

源代碼分析

博客園的登錄頁面非常簡單,查看網頁源代碼,可以發現兩個輸入框的id分別為input1、input2,復選框的id為remember_me,登錄按鈕的id為signin。

還有一段JavaScript代碼,下面來簡單分析一下。

先來看$(function(){});函數:

1 $(function () {
2     $(‘#signin‘).bind(‘click‘, function () {
3         signin_go();
4     }).val(‘登 錄‘);
5 });

$(function(){});是$(document).ready(function(){})的簡寫。當頁面加載完成之后,$(function(){})里的代碼就會被執行。

$(‘#signin‘)表示選取id為signin的元素,即登錄按鈕。

bind()方法為被選元素添加一個或多個事件處理程序,並規定事件發生時運行的函數。

val()方法返回或設置被選元素的值。

當點擊登錄按鈕時,將執行signnin_go()函數。

 

JSEncrypt是一個用於RSA加密的庫。在signnin_go()函數中,通過JSEncrypt對用戶名和密碼進行了加密,setPublicKey()函數里面就是加密的公鑰。

$(‘#remember_me‘).prop(‘checked‘)返回復選框的狀態,勾選時返回true,否則返回false。

兩段加密后的密文和復選框的狀態被保存在一個名為ajax_data的對象里。代碼如下:

1 var encrypt = new JSEncrypt();
2 encrypt.setPublicKey(‘MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp0wHYbg/NOPO3nzMD3dndwS0MccuMeXCHgVlGOoYyFwLdS24Im2e7YyhB0wrUsyYf0/nhzCzBK8ZC9eCWqd0aHbdgOQT6CuFQBMjbyGYvlVYU2ZP7kG9Ft6YV6oc9ambuO7nPZh+bvXH0zDKfi02prknrScAKC0XhadTHT3Al0QIDAQAB‘);
3 var encrypted_input1 = encrypt.encrypt($(‘#input1‘).val());
4 var encrypted_input2 = encrypt.encrypt($(‘#input2‘).val());
5 var ajax_data = {
6     input1: encrypted_input1,
7     input2: encrypted_input2,
8     remember: $(‘#remember_me‘).prop(‘checked‘)
9 };

 

然后就是最主要的$.ajax({})函數了,ajax()方法通過HTTP請求加載遠程數據,在不刷新頁面的情況下與服務器交換數據,返回其創建的 XMLHttpRequest 對象。詳情請參考jQuery ajax - ajax() 方法

 1 $.ajax({
 2     url: ajax_url,
 3     type: ‘post‘,
 4     data: JSON.stringify(ajax_data),
 5     contentType: ‘application/json; charset=utf-8‘,
 6     dataType: ‘json‘,
 7     headers: {‘VerificationToken‘: ‘。。。省略,此處是一大串字符。。。‘},
 8     success: function (data) {
 9         if (data.success) {
10             $(‘#tip_btn‘).html(‘登錄成功,正在重定向...‘);
11             location.href = return_url;
12         } else {}
13     },
14     error: function (xhr) {}
15 });

上面的代碼中做了一些省略。需要特別注意的是headers屬性,刷新之后,VerificationToken的值將會改變,所以在模擬登錄時,必須先獲取這一段字符串。登錄成功后,頁面將進行跳轉。

 

抓包分析

這是登錄時的POST請求,其中有3個參數要特別注意:

技術分享

VerificationToken就是上文中提到的一段變化的字符串。

Ajax異步請求比傳統的同步請求多了一個頭參數,即X-Requested-With。

Content-Type用於定義網絡文件的類型和網頁的編碼,決定瀏覽器將以什么形式、什么編碼讀取這個文件,這就是經常看到一些Asp網頁點擊的結果卻是下載到的一個文件或一張圖片的原因。在這里返回的是json格式的數據。當輸入錯誤的用戶名和密碼時,將得到下面的json數據:

技術分享

正確的用戶名和密碼將得到{"success":true}

 1 import requests
 2 import json
 3 login_url="https://passport.cnblogs.com/user/signin"
 4 return_url="https://home.cnblogs.com/u/xxx/"#我的主頁
 5 session=requests.session()
 6 #獲取VerificationToken
 7 login_page=session.get(login_url)
 8 p=login_page.text.find('VerificationToken')+len('VerificationToken')+4
 9 token=login_page.text[p:login_page.text.find("'",p)]
10 print(token)
11 headers={
12     'Content-Type': 'application/json;charset=UTF-8',
13     'X-Requested-With': 'XMLHttpRequest',
14     'VerificationToken':token
15        }
16 session.headers.update(headers)
17 #可以通過抓包獲取加密后的用戶名和密碼,我將在附錄部分介紹如何在Python中加密
18 data={
19     'input1': "加密的用戶名",
20     'input2': "加密的密碼",
21     'remember':True
22     }
23 
24 #模擬登錄
25 response=session.post(login_url,data=json.dumps(data))
26 print(response.text)
27  #{"success":true}
28  #登錄成功
29 
30 #跳轉到主頁
31 home_page=session.get(return_url)
32  #獲取主頁標題
33 p=home_page.text.find('<title>')+len('<title>')
34 title=home_page.text[p:home_page.text.find('</title>',p)]
35 print(title)
36 #xxx的主頁 - 博客園
37 #如果登錄失敗,跳轉到主頁時返回的結果沒有title標簽,home_page.text將為‘需要登陸‘

 

第二種方法:用自帶的庫(urllib.request

 1 #-*- coding:utf-8 -*-
 2 __author__ = 'Administrator'
 3 
 4 #coding:utf-8
 5 import re
 6 from bs4 import BeautifulSoup
 7 import urllib.request
 8 import urllib.parse
 9 import http.cookiejar
10 import requests
11 
12 
13 def get_opener():
14     cj=http.cookiejar.CookieJar()
15     pro=urllib.request.HTTPCookieProcessor(cj)
16     opener=urllib.request.build_opener(pro)
17     return opener
18 
19 if __name__=="__main__":
20     opener=get_opener()
21     login_url="https://passport.cnblogs.com/user/signin"
22     return_url="https://home.cnblogs.com/u/xxx/"#我的主頁
23   
24     #獲取VerificationToken
25     login_page=opener.open(login_url).read().decode('utf-8')
26     soup=BeautifulSoup(login_page,"html.parser")
27     script=soup.find_all('script')
28     scripttext=script[2].string.strip()
29     p=re.findall('\'VerificationToken\': \'.*?\'',scripttext)[0]
30     start=len('VerificationToken')+5
31     token=p[start:-1]
32 
33     headers={
34     'Content-Type': 'application/json;charset=UTF-8',
35     'X-Requested-With': 'XMLHttpRequest',
36     'VerificationToken':token
37        }
38 
39     #可以通過抓包獲取加密后的用戶名和密碼
40     data={
41     'input1': "加密的用戶名",
42     'input2': "加密的密碼",
43     'remember':True
44     }
45     heads=[]
46     for key,value in headers.items():
47         heads.append((key,value))
48     login_data=urllib.parse.urlencode(data).encode('utf-8')
49     opener.addheaders=heads
50     Req=urllib.request.Request(login_url,data=login_data)
51     response= opener.open(Req)
52     print(response.read().decode('utf-8'))
53     #{"success":true}
54     #登錄成功
55 
56    #跳轉到主頁
57     home_page=opener.open(return_url)
58     #獲取主頁標題
59     soup=BeautifulSoup(home_page.read().decode('utf-8'),"html.parser")
60     p=soup.find('title')
61     print(p.text)
62     #xxx的主頁 - 博客園
63     #如果登錄失敗,跳轉到主頁時返回的結果沒有title標簽,則‘需要登陸‘

 


免責聲明!

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



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