python网络爬虫学习
- 用urlib中的urlopen()函数向网页发送信息
data参数:GET用于获取信息(default),POST向服务器提交数据
注意: data有自己的格式,需要urllib.parse.urlencode()函数将str转为data - 以有道翻译为目标
打开审查元素,观察Network内容在输入翻译内容前后的变化,找到此新增内容
headers标签下记录Request URL和Form Data,初步设想用如下代码实现:
# -*- coding: UTF-8 -*-
from urllib import request
from urllib import parse
import json
if __name__ == "__main__":
url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
dic = {'i': 'piggy', 'from': 'AUTO', 'to': 'AUTO', 'smartresult': 'dict', 'client': 'fanyideskweb',
'salt': '15940911299981', 'ts': '1594091129319', 'sign': 'f838ebbe5470a6779ff7834a644f1665',
'bv': '02a6ad4308a3443b3732d855273259bf', 'doctype': 'json', 'version': '2.1', 'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME'}
data = parse.urlencode(dic).encode('utf-8')
print(data)
response = request.urlopen(url, data)
html = response.read().decode('utf-8')
print(html)
tr_html = json.loads(html)
print(tr_html)
tr_html = tr_html['translateResult'][0][0]['tgt']
print(tr_html)
注意:
- 需要使用JSON处理数据
- 最后的结果需要根据格式提取我们想要的内容
然鹅,打印结果是
{"errorCode":50}
考虑网站可能加入反爬虫机制,查看Form Data发现salt、sign在每次请求时都会产生新的值
一种可能是服务器发送salt、sign值,另一种可能是它们可以在本地自动生成
查看fanyi.js文件 ,搜索salt关键字,找到生成salt和sign的代码
function(e, t) {
var n = e("./jquery-1.7");
e("./utils");
e("./md5");
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 + "mmbP%A-r6U3Nw(n]BjuEU")
}
};
sign:当前时间与1-10的随机数拼接成的str
salt:“fanyideskweb” + 要翻译的文本 + sign + “mmbP%A-r6U3Nw(n]BjuEU” 的md5加密值
明白了生成机制,我们在文章最初的代码加入生成sign和salt的代码
# -*- coding: UTF-8 -*-
import urllib
import json
import time
import random
import hashlib
from pip._vendor import requests
if __name__ == "__main__":
i = 'piggy'
ts = str(int(time.time() * 1000))
sign = str(int(time.time() * 1000) + random.randint(1, 10))
salt = 'fanyideskweb' + i + sign + 'mmbP%A-r6U3Nw(n]BjuEU'
salt = hashlib.md5(salt.encode('utf-8')).hexdigest()
bv = '5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
bv = hashlib.md5(bv.encode('utf-8')).hexdigest()
url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
data = {'i': i,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': salt,
'ts': ts,
'sign': sign,
'bv': bv,
'doctype': 'json', 'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME'
}
# data = urllib.parse.urlencode(data).encode('utf-8')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
'Referer': 'http://fanyi.youdao.com/',
'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=1377122766.003579; OUTFOX_SEARCH_USER_ID="-561197241@10.108.160.18"; _ga=GA1.2.914587152.1588988523; _ntes_nnid=00a5617e0331e2f359603609552a51b6,1589709384596; JSESSIONID=aaaWSmPbq4UeeguYTcXmx; ___rl__test__cookies=1594260388863'
}
# headers = urllib.parse.urlencode(headers).encode('utf-8')
# re = urllib.request.Request(url, data=data, method='POST')
# response = urllib.request.urlopen(re)
response = requests.post(url, headers = headers, data = data)
html = response.content.decode('utf-8')
print(html)
tr_html = json.loads(html)
print(tr_html)
# tr_html = tr_html['translateResult'][0][0]['tgt']
print(tr_html)
hashlib md5() 生成str对应的md5
python: time.time() #从1970.1.1开始到当前时刻的秒数
js: (new Date).getTime() #1970.1.1开始到当前时刻的毫秒数
按照此代码已无法成功请求 时间2020.07
其他博客的方法也已失效
如果用某些博客说的去掉url中的_o确实可以成功,但翻译结果和正常有差别,而且删去_o根本不需要考虑salt和sign的生成。