学会爬取静态页面的数据后,下面固然是学习爬取动态页面的数据。javascript
什么是动态页面呢?java
有时候咱们再用requests抓取页面的时候,获得的结果可能和在浏览器中看到的不同:在浏览器中能够看到正常显示的页面数据,但在使用requests获得的结果中却没有。这是由于requests获取的都是原始的HTML文档,而浏览器中的页面则是通过JavaScript处理数据后生成的结果,这些数据的来源有多种,多是经过Ajax加载的,多是包含在HTML文档中的,也多是通过JavaScript和特定算法计算后生成的。python
本篇整理记录爬取其中经过JavaScript混淆加密来渲染的页面web
案例网站 有道翻译:http://fanyi.youdao.com/算法
打开chrome开发者工具,刷新页面,分析页面
chrome
输入‘萌新’点击翻译后,右边的XHR栏中,出现一条类型为xhr的数据请求,点击查看后。
POST请求地址为:http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
再看一下请求带过去的参数是哪些?json
OK!!!其中 i 这个参数就是咱们须要翻译的内容。那么直接复制请求头以及所需参数来构建requests请求。浏览器
构建requests请求cookie
headers = { "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Cookie": "OUTFOX_SEARCH_USER_ID=-1576851776@10.169.0.84; JSESSIONID=" "aaaBxpJhsD9bZgfYbsJax; OUTFOX_SEARCH_USER_ID_NCOO=2138649720.2208343;" " ___rl__test__cookies=1581141334922", "Referer": "http://fanyi.youdao.com/", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" } url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule" form_data = { "i": '萌新', "from": "AUTO", "to": "AUTO", "smartresult": "dict", "client": "fanyideskweb", "salt": '15811630953552', "sign": '95f6b7ff43ba04c257097dabd115645e', "ts": '1581163095355', "bv": 'd6c3cd962e29b66abe48fcb8f4dd7f7d', "doctype": "json", "version": "2.1", "keyfrom": "fanyi.web", "action": "FY_BY_CLICKBUTTION" } response = requests.post(url=url, headers=headers, data=form_data) print(response.text)
运行后结果:app
程序返回了一个错误码!
当咱们尝试翻译不一样的内容后,咱们发现参数 salt 、sign、ts、bv是会变化的。那么就该思考变化的参数是怎么来的呢?
发现js文件
此时发现这个数据请求它指向 fanyi.min.js:1 这个js文件,咱们点击这个js文件
出现这个界面,一堆的JavaScript代码,看也看不懂,咱们点击左下角的{}让它展开。
使用chrome的打断点功能
在方框处添加以前数据请求的POST地址:http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
而后,从新点击翻译按钮,断点成功屏幕会变为一半为灰色。 发现,行号从新定位在了7570行,展开右边 Call Stack,点击其中的
t.translate发现有咱们须要的参数。
继续深刻
将鼠标放入generateSaltSign上面,出现了如图所示的连接,点击跳转至8363行。
此时咱们就找到了须要的参数salt、sign、ts、bv的源头。
将鼠标点击8363行,出现蓝色的标记即为打上一个断点。而后点击上方图中所示按钮。再点击一下翻译按钮。
经过上面的操做,咱们找出了4个参数的源头,正是经过上图中的JavaScript代码来计算出来的。下面就用python来构造这4个参数
def get_ts(): ts = str(time.time() * 1000) return ts
def get_bv(): appVersion = "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" m = hashlib.md5() m.update(appVersion.encode("utf-8")) bv = m.hexdigest() return bv
def get_salt(): salt = str(time.time() * 1000) + str(random.random() * 10) return salt
def get_sign(myinput): a = "fanyideskweb" b = myinput c = get_salt() d = "n%A-rKaT5fb[Gy?;N5@Tj" str_data = a + b + c + d m = hashlib.md5() m.update(str_data.encode("utf-8")) sign = m.hexdigest() return sign
import requests import time import json import hashlib import random def get_ts(): ts = str(time.time() * 1000) return ts def get_bv(): appVersion = "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" m = hashlib.md5() m.update(appVersion.encode("utf-8")) bv = m.hexdigest() return bv def get_salt(): salt = str(time.time() * 1000) + str(random.random() * 10) return salt def get_sign(): a = "fanyideskweb" b = "萌新" c = get_salt() d = "n%A-rKaT5fb[Gy?;N5@Tj" str_data = a + b + c + d m = hashlib.md5() m.update(str_data.encode("utf-8")) sign = m.hexdigest() return sign def get_request(): headers = { "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Cookie": "OUTFOX_SEARCH_USER_ID=-1576851776@10.169.0.84; JSESSIONID=" "aaaBxpJhsD9bZgfYbsJax; OUTFOX_SEARCH_USER_ID_NCOO=2138649720.2208343;" " ___rl__test__cookies=1581141334922", "Referer": "http://fanyi.youdao.com/", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" } url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule" form_data = { "i": '萌新', "from": "AUTO", "to": "AUTO", "smartresult": "dict", "client": "fanyideskweb", "salt": get_salt(), "sign": get_sign(), "ts": get_ts(), "bv": get_bv(), "doctype": "json", "version": "2.1", "keyfrom": "fanyi.web", "action": "FY_BY_CLICKBUTTION" } response = requests.post(url=url, headers=headers, data=form_data) print("翻译结果是:" + str(json.loads(response.text)['translateResult'][0][0]['tgt'])) if __name__ == '__main__': get_request()
既然,咱们能找到这些参数的规律,咱们能够打包成 .exe 可执行文件作成翻译软件,分享给身边的小伙伴学习交流使用!!!
参考:Python中将.py文件打包成.exe可执行文件的简单方法