更新時間:2019年02月16日18時26分 來源:python培訓(xùn) 瀏覽次數(shù):
目前網(wǎng)上很多模擬登錄知乎的代碼已經(jīng)無法使用,即使是二、三月的代碼也已經(jīng)無法模擬登陸知乎,現(xiàn)在將新版知乎的模擬登錄代碼和講解發(fā)布出來。而這些都是需要python來實現(xiàn)的,也算是學(xué)會python的好處之一吧。
零、開發(fā)環(huán)境
開發(fā)工具:Pycharm
Python版本:3.6
運行環(huán)境:Win10
一、代碼和講解
# 利用requests 模擬登陸
import requests
import http.cookiejar as cookielib
import re
import time
import hmac
from hashlib import sha1
import json
import base64
from PIL import Image
# 利用session保持鏈接
session = requests.session()
session.cookies = cookielib.LWPCookieJar(filename="cookies.txt") # cookie存儲文件,
# 提取保存的cookie
try:
session.cookies.load(ignore_discard=True) # 從文件中讀取cookie
except:
print("cookie 未能加載")
# 偽造header
agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
header = {
"HOST": "www.zhihu.com",
"Referer": "https://www.zhihu.com",
"User-Agent": agent,
'Connection': 'keep-alive'
}
def is_login():
# 通過個人中心頁面返回狀態(tài)碼來判斷是否登錄
# 通過allow_redirects 設(shè)置為不獲取重定向后的頁面
response = session.get("https://www.zhihu.com/inbox", headers=header, allow_redirects=False)
if response.status_code != 200:
zhihu_login("+8618511693445", "123*asd")
else:
print("你已經(jīng)登陸了")
def get_xsrf_dc0():
# 獲取xsrf code和d_c0
# 在請求登錄頁面的時候頁面會將xsrf code 和d_c0加入到cookie中返回給客戶端
response = session.get("https://www.zhihu.com/signup", headers=header)
return response.cookies["_xsrf"], response.cookies["d_c0"]
def get_signature(time_str):
# 生成signature,利用hmac加密
# 根據(jù)分析之后的js,可發(fā)現(xiàn)里面有一段是進行hmac加密的
# 分析執(zhí)行加密的js 代碼,可得出加密的字段,利用python 進行hmac幾碼
h = hmac.new(key='d1b964811afb40118a12068ff74a12f4'.encode('utf-8'), digestmod=sha1)
grant_type = 'password'
client_id = 'c3cef7c66a1843f8b3a9e6a1e3160e20'
source = 'com.zhihu.web'
now = time_str
h.update((grant_type + client_id + source + now).encode('utf-8'))
return h.hexdigest()
def get_identifying_code(headers):
# 判斷頁面是否需要填寫驗證碼
# 如果需要填寫則彈出驗證碼,進行手動填寫
# 請求驗證碼的url 后的參數(shù)lang=en,意思是取得英文驗證碼
# 原因是知乎的驗證碼分為中文和英文兩種
# 中文驗證碼是通過選擇倒置的漢字驗證的,破解起來相對來說比較困難,
# 英文的驗證碼則是輸入驗證碼內(nèi)容即可,破解起來相對簡單,因此使用英文驗證碼
response = session.get('https://www.zhihu.com/api/v3/oauth/captcha?lang=en', headers=headers)
# 盤但是否存在驗證碼
r = re.findall('"show_captcha":(\w+)', response.text)
if r[0] == 'false':
return ''
else:
response = session.put('https://www.zhihu.com/api/v3/oauth/captcha?lang=en', headers=header)
show_captcha = json.loads(response.text)['img_base64']
with open('captcha.jpg', 'wb') as f:
f.write(base64.b64decode(show_captcha))
im = Image.open('captcha.jpg')
im.show()
im.close()
captcha = input('輸入驗證碼:')
session.post('https://www.zhihu.com/api/v3/oauth/captcha?lang=en', headers=header,
data={"input_text": captcha})
return captcha
def zhihu_login(account, password):
'''知乎登陸'''
post_url = 'https://www.zhihu.com/api/v3/oauth/sign_in'
XXsrftoken, XUDID = get_xsrf_dc0()
header.update({
"authorization": "oauth c3cef7c66a1843f8b3a9e6a1e3160e20", # 固定值
"X-Xsrftoken": XXsrftoken,
})
time_str = str(int((time.time() * 1000)))
# 直接寫在引號內(nèi)的值為固定值,
# 只要知乎不改版反爬蟲措施,這些值都不湖邊
post_data = {
"client_id": "c3cef7c66a1843f8b3a9e6a1e3160e20",
"grant_type": "password",
"timestamp": time_str,
"source": "com.zhihu.web",
"password": password,
"username": account,
"captcha": "",
"lang": "en",
"ref_source": "homepage",
"utm_source": "",
"signature": get_signature(time_str),
'captcha': get_identifying_code(header)
}
response = session.post(post_url, data=post_data, headers=header, cookies=session.cookies)
if response.status_code == 201:
# 保存cookie,下次直接讀取保存的cookie,不用再次登錄
session.cookies.save()
else:
print("登錄失敗")
if __name__ == '__main__':
is_login()