JS的解析

学习目标:
  1. 了解 定位js的方法
  2. 了解 添加断点观察js的执行过程的方法
  3. 应用 js2py获取js的方法

1 确定js的位置

对于前面人人网的案例,我们知道了url地址中有部分参数,但是参数是如何生成的呢?

毫无疑问,参数肯定是js生成的,那么如何获取这些参数的规律呢?通过下面的学习来了解

1.1 观察按钮的绑定js事件

通过点击按钮,然后点击Event Listener,部分网站可以找到绑定的事件,对应的,只需要点击即可跳转到js的位置

1.2 通过search all file 来搜索

部分网站的按钮可能并没有绑定js事件监听,那么这个时候可以通过搜索请求中的关键字来找到js的位置,比如livecell

点击美化输出选项

可以继续在其中搜索关键字

2 观察js的执行过程

找到js的位置之后,我们可以来通过观察js的位置,找到js具体在如何执行,后续我们可以通过python程序来模拟js的执行,或者是使用类似js2py直接把js代码转化为python程序去执行

观察js的执行过程最简单的方式是添加断点

添加断点的方式:在左边行号点击即可添加,对应的右边BreakPoints中会出现现有的所有断点

添加断点之后继续点击登录,每次程序在断点位置都会停止,通过如果该行有变量产生,都会把变量的结果展示在Scoope中

在上图的右上角有1,2,3三个功能,分别表示:
- 1:继续执行到下一个断点
- 2:进入调用的函数中
- 3:从调用的函数中跳出来

3 js2py的使用

在知道了js如何生成我们想要的数据之后,那么接下来我们就需要使用程序获取js执行之后的结果了

3.1 js2py的介绍

js2py是一个js的翻译工具,也是一个通过纯python实现的js的解释器,github上源码与示例

3.2 js的执行思路

js的执行方式大致分为两种:

  1. 在了解了js内容和执行顺序之后,通过python来完成js的执行过程,得到结果
  2. 在了解了js内容和执行顺序之后,使用类似js2py的模块来执js代码,得到结果

但是在使用python程序实现js的执行时候,需要观察的js的每一个步骤,非常麻烦,所以更多的时候我们会选择使用类似js2py的模块去执行js,接下来我们来使用js2py实现人人网登录参数的获取

3.3 具体的实现

定位进行登录js代码

formSubmit: function() {var e, t = {};$(".login").addEventListener("click", function() {t.phoneNum = $(".phonenum").value,t.password = $(".password").value,e = loginValidate(t),t.c1 = c1 || 0,e.flag ? ajaxFunc("get", "http://activity.renren.com/livecell/rKey", "", function(e) {var n = JSON.parse(e).data;if (0 == n.code) {t.password = t.password.split("").reverse().join(""),setMaxDigits(130);var o = new RSAKeyPair(n.e,"",n.n), r = encryptedString(o, t.password);t.password = r,t.rKey = n.rkey} elsetoast("公钥获取失败"),t.rKey = "";ajaxFunc("post", "http://activity.renren.com/livecell/ajax/clog", t, function(e) {var e = JSON.parse(e).logInfo;0 == e.code ? location.href = localStorage.getItem("url") || "" : toast(e.msg || "登录出错")})}) : toast(e.msg)})}
从代码中我们知道:
  1. 我们要登录需要对密码进行加密和获取rkey字段的值
  2. rkey字段的值我们直接发送请求rkey请求就可以获得
  3. 密码是先反转然后使用RSA进行加密, js代码很复杂, 我们希望能通过在python中执行js来实现
实现思路:
  1. 使用session发送rKey获取登录需要信息

    • url: http://activity.renren.com/livecell/rKey
    • 方法: get
  2. 根据获取信息对密码进行加密
    2.1 准备用户名和密码

    2.2 使用js2py生成js的执行环境:context

    2.3 拷贝使用到js文件的内容到本项目中

    2.4 读取js文件的内容,使用context来执行它们

    2.5 向context环境中添加需要数据

    2.6 使用context执行加密密码的js字符串

    2.7 通过context获取加密后密码信息

  3. 使用session发送登录请求

    • URL: http://activity.renren.com/livecell/ajax/clog

    • 请求方法: POST

    • 数据:

      phoneNum: xxxxxxx
      password: (加密后生产的)
      c1: 0
      rKey: rkey请求获取的
      
具体代码

需要提前下载几个js文件到本地:

BigInt.js

RSA.js

Barrett.js

import requests
import json
import js2py# - 实现思路:
#   - 使用session发送rKey获取登录需要信息
#     - url: http://activity.renren.com/livecell/rKey
#     - 方法: get
#  获取session对象
session = requests.session()
headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36","X-Requested-With": "XMLHttpRequest","Content-Type":"application/x-www-form-urlencoded"
}
# 设置session的请求头信息
session.headers = headersresponse = session.get("http://activity.renren.com/livecell/rKey")
# print(response.content.decode())
n = json.loads(response.content)['data']#   - 根据获取信息对密码进行加密
#     - 准备用户名和密码
phoneNum = "131..."
password = "****"
#     - 使用js2py生成js的执行环境:context
context = js2py.EvalJs()
#     - 拷贝使用到js文件的内容到本项目中
#     - 读取js文件的内容,使用context来执行它们
with open("BigInt.js", 'r', encoding='utf8') as f:context.execute(f.read())with open("RSA.js", 'r', encoding='utf8') as f:context.execute(f.read())
with open("Barrett.js", 'r', encoding='utf8') as f:context.execute(f.read())# - 向context环境中添加需要数据
context.t = {'password': password}
context.n = n
#     - 执行加密密码的js字符
js = '''t.password = t.password.split("").reverse().join(""),setMaxDigits(130);var o = new RSAKeyPair(n.e,"",n.n), r = encryptedString(o, t.password);'''
context.execute(js)
# - 通过context获取加密后密码信息
# print(context.r)
password = context.r
#   - 使用session发送登录请求
#     - URL: http://activity.renren.com/livecell/ajax/clog
#     - 请求方法: POST
#     - 数据:
#       - phoneNum: 15565280933
#       - password: (加密后生产的)
#       - c1: 0
#       - rKey: rkey请求获取的
data = {'phoneNum': '131....','password': password,'c1':0,'rKey':n['rkey']
}# print(session.headers)
response = session.post("http://activity.renren.com/livecell/ajax/clog", data=data)
print(response.content.decode())# 访问登录的资源
response = session.get("http://activity.renren.com/home#profile")
print(response.content.decode())

小结

  1. 通过在chrome中观察元素的绑定事件可以确定js
  2. 通过在chrome中search all file 搜索关键字可以确定js的位置
  3. 观察js的数据生成过程可以使用添加断点的方式观察
  4. js2py的使用
    • 需要准备js的内容
    • 生成js的执行环境
    • 在执行环境中执行js的字符串,传入数据,获取结果

【综合案例】:有道翻译
知识点:
1、python中的哈希处理:md5()

import js2pyimport hashlibdata = 'python37'# 创建hash对象
md5 = hashlib.md5()# 向hash对象中添加需要做hash运算的字符串
md5.update(data.encode())# 获取字符串的hash值
result = md5.hexdigest()
print(result)


分析过程:进行抓包:



接下来通过search相关内容进行寻找:

import requests
import hashlib
import time
import random
import jsonclass Youdao(object):def __init__(self):self.url='http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'self.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','Cookie': "OUTFOX_SEARCH_USER_ID=-1628507307@10.108.160.17; OUTFOX_SEARCH_USER_ID_NCOO=1058312939.7835485; _ntes_nnid=7c814c8475605712d1b72e0446d52cf2,1590040388694; JSESSIONID=aaaRXPpDC6D_h4ZVYTYmx; ___rl__test__cookies=1594283781148",'Referer': 'http://fanyi.youdao.com/'}self.formdata = Noneself.word = input("请输入需要翻译的单词或句子:")def generate_formdata(self):'''ts: r = "" + (new Date).getTime(),salt: ts + parseInt(10 * Math.random(), 10),sign: n.md5("fanyideskweb" + e + i + "mmbP%A-r6U3Nw(n]BjuEU")'''ts = str(int(time.time()*1000))# print(ts)salt = ts + str(random.randint(0,9))# print(salt)temstr = "fanyideskweb" + self.word + salt + "mmbP%A-r6U3Nw(n]BjuEU"# 创建hash对象md5 = hashlib.md5()# 向hash对象中添加需要做hash运算的字符串.注意,字符串需要转换成bytes类型md5.update(temstr.encode())# 将结果转成16进制sign = md5.hexdigest()self.formdata = {"i": self.word,"from": "AUTO","to": "AUTO","smartresult": "dict","client": "fanyideskweb","salt": salt,"sign": sign,"ts": ts,"bv": "02a6ad4308a3443b3732d855273259bf","doctype": "json","version": "2.1","keyfrom": "fanyi.web","action": "FY_BY_REALTlME"}def get_data(self):response = requests.post(self.url,data=self.formdata,headers =self.headers)return response.contentdef parse_data(self,data):# print(type(data.decode()))str = data.decode()# print(type(json.loads(str)))dict_data = json.loads(str)print("有道翻译结果:" + dict_data['translateResult'][0][0]['tgt'])def run(self):# url# headers# formdataself.generate_formdata()# print(self.formdata)# 发送请求,获取响应data = self.get_data()# print(data)# 解析数据self.parse_data(data)if __name__ == '__main__':youdao = Youdao()youdao.run()

运行结果:

python网络爬虫系列(十一)——JS的解析相关推荐

  1. python网络爬虫系列教程_Python网络爬虫系列教程连载 ----长期更新中,敬请关注!...

    感谢大家长期对Python爱好者社区的支持,后期Python爱好者社区推出Python网络爬虫系列教程.欢迎大家关注.以下系列教程大纲,欢迎大家补充.视频长期连载更新中 --------------- ...

  2. python网络爬虫系列教程——python中lxml库应用全解(xpath表达式)

    全栈工程师开发手册 (作者:栾鹏) python教程全解 python网络爬虫lxml库的应用全解. 在线安装方法:cmd中输入"pip install lxml" 离线安装,下载 ...

  3. python网络爬虫系列教程——python中requests库应用全解

    全栈工程师开发手册 (作者:栾鹏) python教程全解 python中requests库的基础应用,网页数据挖掘的常用库之一.也就是说最主要的功能是从网页抓取数据. 使用前需要先联网安装reques ...

  4. python网络爬虫系列教程——python中pyquery库应用全解

    全栈工程师开发手册 (作者:栾鹏) python教程全解 python网络爬虫lxml库的应用全解. 在线安装方法:cmd中输入"pip install pyquery" 离线安装 ...

  5. Python网络爬虫系列(一)

    本节主要是体会Python进行网络爬虫的大概流程,代码部分需其它基础,后续会具体介绍. 一.为什么推荐Python进行网络爬虫 (1)上手容易 (2)免费开源,使用不受限制 (3)解释执行,跨平台不受 ...

  6. python网络爬虫系列教程——python网络数据爬虫误区,让你的爬虫更像人类

    1 前言 近期,有些朋友问我一些关于如何应对反爬虫的问题.由于好多朋友都在问,因此决定写一篇此类的博客.把我知道的一些方法,分享给大家.博主属于小菜级别,玩爬虫也完全是处于兴趣爱好,如有不足之处,还望 ...

  7. python网络爬虫系列(0)——爬虫概述 http协议复习

    一.爬虫概述 知识点: 了解 爬虫的概念 了解 爬虫的作用 了解 爬虫的分类 掌握 爬虫的流程 1. 爬虫的概念 模拟浏览器,发送请求,获取响应 网络爬虫(又被称为网页蜘蛛,网络机器人)就是模拟客户端 ...

  8. Python实训day14pm【Python网络爬虫综合大作业-参考解析】

    Python实训-15天-博客汇总表 题目:天气数据的爬取和统计 大作业题目思路引导:定时爬取每个地级市的实时天气状况.存入excel中.为每个城市生成html展示.历史excel文件以每日为单位归档 ...

  9. python网络爬虫系列(八)——常见的反爬手段和解决方法

    常见的反爬手段和解决思路 学习目标 了解 服务器反爬的原因 了解 服务器常反什么样的爬虫 了解 反爬虫领域常见的一些概念 了解 反爬的三个方向 了解 常见基于身份识别进行反爬 了解 常见基于爬虫行为进 ...

最新文章

  1. 谷歌发布 RLDS,在强化学习生成、共享和使用数据集
  2. pandas使用shift方法进行特征差分
  3. Android测试框架-uiautomator
  4. Python 解决写入csv中间隔一行空行问题
  5. DNS服务器以及正向名称解析机制
  6. [转载]SQL Server 2005 Data Mining简介
  7. bilibili有电脑版吗_电脑版和平精英你期待吗?可惜国内并未上线
  8. C++ gnome sort 侏儒排序的实现算法(附完整源码)
  9. 求职特训营火热来袭,阿里大咖教你制作专业简历
  10. java asm 中文文档_Java ASM3学习(3)
  11. windows CMD.exe下写路径太长的解决方案
  12. canvas笔记-画三角形并计算其外心(含算法其他绘图框架类似)
  13. Git笔记(5) 状态记录
  14. 1032. 挖掘机技术哪家强(20)-PAT乙级真题
  15. CentOS/Ubuntu 14.10 安装 phpstorm
  16. 嵌入式开发学习学习路线
  17. 广大银行java 面试_2018光大银行春季招聘面试题目及答案
  18. windows Internet Connection Sharing(ICS)服务的启动
  19. ftp服务器上图片文件显示不出来,ftp服务器上图片文件显示
  20. 乱弹琴20140421

热门文章

  1. Python多线程--互斥锁、死锁
  2. ancestral 箭头符号,译林版《牛津高中英语》模块五 高二上学期
  3. matlab如何用代码导入文件_20+行Matlab代码实现文件扫描
  4. Docker 精通之 Dockerfile
  5. 【Python + Selenium】之JS定位总结
  6. pojo java_Java——POJO总结
  7. 单片机oled显示浮点数函数_问中文编程在单片机上实现一个电子时钟,总共有几步?...
  8. Oracle PL/SQL块 多表查询(emp员工表、dept部门表、salgrade工资等级表)
  9. 轻松理解UML用例图时序图类图的教程
  10. 给vmware虚拟机中的ubuntu 14.04扩大磁盘分区