python3爬蟲遇到了反爬
當你興沖沖的開啟一個網頁,發現裡面的資源好棒,能批量下載就好了,然後感謝寫個爬蟲down一下,結果,一頓操作之後,發現網站竟然有反爬措施,尷尬了。
接下來的幾篇文章,我們研究一下各種反爬蟲套路,當然網際網路沒有100%的反爬措施,只要你能使用瀏覽器訪問的網頁,都是可以爬取到了,所有的人不能杜絕爬蟲,只能在一定程度上增加你爬取的成本,說白了,就是讓你的技術爬不到~
爬蟲和反爬蟲一直都是這個領域程式設計師對抗的基礎,從最簡單的UA限制,到略微複雜一些的IP限制,使用者限制,技術都是不斷髮展的,但是,不怕賊偷,就怕賊惦記,只要你的網站內容有價值,放心,一堆爬蟲coder盯著呢?
emmmm....
搞定javascript加密
js加密最簡單的是採用md5進行的,我們通過http://fanyi.youdao.com/
來演示本篇部落格內容
fanyi.min.js
,繼續追蹤,滑鼠在這個檔名上面停留一下就可以獲取到基本資訊,我們點選跟請求相關的那個方法對應的檔案連結,跳轉到方法內部
這個地方有個操作細節,你需要學會,點選檔案之後,跳轉到的JS檔案是壓縮之後的,進行一下格式化操作
拿到原始碼 t.translate = function(e, t) {
_ = f("#language").val();
var n = x.val()
, r = g.generateSaltSign(n)
, i = n.length;
if (F(),
T.text(i),
i > 5e3) {
var a = n;
n = a.substr(0, 5e3),
r = g.generateSaltSign(n);
var s = a.substr(5e3);
s = (s = s.trim()).substr(0, 3),
f("#inputTargetError").text("有道翻譯字數限制為5000字,“" + s + "”及其後面沒有被翻譯!").show(),
T.addClass("fonts__overed")
} else
T.removeClass("fonts__overed"),
f("#inputTargetError").hide();
d.isWeb(n) ? o() : l({
i: n,
from: C,
to: S,
smartresult: "dict",
client: k,
salt: r.salt,
sign: r.sign,
ts: r.ts,
bv: r.bv,
doctype: "json",
version: "2.1",
keyfrom: "fanyi.web",
action: e || "FY_BY_DEFAULT",
typoResult: !1
}, t)
}
複製程式碼
引數分析
- i 表示 帶翻譯的詞語
- from 設定為
AUTO
- to 設定為
AUTO
- smartresult 預設值
dict
- client 翻譯的客戶端:預設應該為
fanyideskweb
- salt 第一個變數 需要查閱生成規則
- sign 第二個變數 需要查閱生成規則
- ts
- bv
- 其餘的引數保持預設即可
重點引數
- salt
- sign
- ts
- bv
程式碼的複查當中找到引數來源
var r = function(e) {
var t = n.md5(navigator.appVersion)
, r = "" + (new Date).getTime()
, i = r + parseInt(10 * Math.random(), 10);
return {
ts: r,
bv: t,
salt: i,
sign: n.md5("fanyideskweb" + e + i + "1L5ja}w$puC.v_Kz3@yYn")
}
複製程式碼
OK,我們已經獲取到引數的內容了
- ts = r 表示當前的時間戳
- salt 用r去加上一個隨機數
- sign 為 一個特殊的md5,中間重點注意
e
其實就是你要翻譯的詞語 - navigator.appVersion 這個比較容易,在開發者工具中執行一下就可以得到了
5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
程式碼嘗試
準備好這麼多材料之後,剩下的就是編碼了,我們開始吧,這個地方依據的是JS的原始碼,然後轉換成Python即可,沒有特別難的地方
引數的生成
def generate_salt_sign(translate):
# var t = n.md5(navigator.appVersion)
app_version = "5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
bv = hashlib.md5(app_version.encode(encoding='UTF-8')).hexdigest()
# r = "" + (new Date).getTime()
ts = str(int(round(time.time(),3)*1000))
# i = r + parseInt(10 * Math.random(), 10);
salt = ts + str(random.randint(1,10))
# sign: n.md5("fanyideskweb" + e + i + "1L5ja}w$puC.v_Kz3@yYn")
sign = hashlib.md5(("fanyideskweb"+translate+salt+"1L5ja}w$puC.v_Kz3@yYn").encode(encoding='utf-8')).hexdigest()
return salt,sign,ts,bv
複製程式碼
引數的拼接與header的準備
def params():
data = {}
translate = 'morning'
client = 'fanyideskweb'
data['i'] = translate
data['from'] = 'AUTO'
data['to'] = 'AUTO'
data['smartresult'] = 'dict'
data['client'] = client
data['salt'],data['sign'],data['ts'],data['bv'] = generate_salt_sign(translate)
data['doctype'] = 'json'
data['version'] = '2.1'
data['keyfrom'] = 'fanyi.web'
data['action'] = 'FY_BY_REALTIME'
data['typoResult'] = 'false'
return data
複製程式碼
發起請求
def tran():
data = params()
headers = {}
headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
headers["Referer"] = "http://fanyi.youdao.com/"
headers["Cookie"] = "OUTFOX_SEARCH_USER_ID=-1868577286@222.222.147.75;"
with requests.post("http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule",headers=headers,data=data) as res:
print(res.text)
if __name__ == '__main__':
tran()
複製程式碼
結果展示
{"translateResult":[[{"tgt":"早....","src":"morning"}]],"errorCode":0,"type":"en2zh-CHS","smartResult":{"entries":["","n. 早晨;黎明;初期\r\n"],"type":1}}
複製程式碼
得到資料之後就表示我們的目標完成了~
本篇部落格的反爬內容搞定~
關注微信公眾賬號,回覆0401獲取原始碼