爬虫之JS解析,Python模拟JS代码运行。(附带模拟人人网登录案例)

六、JS解析

1.定位js文件
  • 1.通过initiator定位到js文件
  • 2.通过search搜索关键字定位到js文件
  • 3.通过元素绑定的事件监听函数找到js文件,Event Listeners
  • 注:三种方法不能保证每一种都能找到js文件,都试试
2.js代码分析,掌握加密步骤
  • 可以加断点
3.模拟重现
  • 1.通过第三方js加载模块直接加载js运行,js2py pyv8 execjs等

    • js2py模块,是一个js的发翻译工具,也是一个通过纯python实现的js解释器

    • js执行思路

      • 1.在了解js内容和执行顺序后,通过python来完成js的执行过程,得到结果
      • 2.在了解js内容和执行顺序之后,使用类似js2py的模块来执行js代码,得到结果
      • 但是在使用python程序实现js执行的时候,需要观察js的每一个步骤,非常麻烦,所以更多时候我们会选择使用类似js2py的模块去执行js,接下来我们来使用js2py实现人人网登录参数的获取
    • 具体实现

      import js2py
      import requests
      
      # 创建js执行环境
      context = js2py.EvalJs()
      
      
      # 手机端的headers
      headers = {
          "User-Agent":"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Mobile Safari/537.36"
      }
      # 先把js文件下载下来
      big_js = requests.get("http://s.xnimg.cn/a85738/wap/mobile/wechatLive/js/BigInt.js",headers=headers).content.decode()
      # 然后加载js文件
      context.execute(big_js)
      # 再调用这个函数
      context.execute("setMaxDigits(130);")
      
      
      
    • 人人网登录

      import requests
      import js2py
      import json
      
      
      def login():
          # 创建session对象
          session = requests.session()
          # 设置请求头
          session.headers={
              "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Mobile Safari/537.36"
          }
          # 发送获取公钥数据包的get请求  获取rkey
          response = session.get('http://activity.renren.com/livecell/rKey')
          # print(response.content.decode())
          # 创建n
          n = json.loads(response.content.decode())['data']
          # print(n)
          # 创建t
          t = {
              "password":"wangtaotao."
          }
          # 获取前置js代码
          rsa_js = session.get("http://s.xnimg.cn/a85738/wap/mobile/wechatLive/js/RSA.js").content.decode()
          bigint_js = session.get("http://s.xnimg.cn/a85738/wap/mobile/wechatLive/js/BigInt.js",).content.decode()
          barrett_js = session.get("http://s.xnimg.cn/a85738/wap/mobile/wechatLive/js/Barrett.js",).content.decode()
      
      
          # 创建js环境对象
          context = js2py.EvalJs()
      
          # 将变量和js代码加载到环境对象中执行
          context.execute(rsa_js)
          context.execute(bigint_js)
          context.execute(barrett_js)
          context.n = n
          context.t = t
          # 将关键js代码放到环境对象中执行
          pwd_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(pwd_js)
          # 获取加密密码
          # print(context.r)
      
          # 构建formdata
          formdata = {
              "phoneNum": "15041890905",
              "password": context.r,
              "c1": -100,
              "rKey": n["rkey"]
          }
          # print(formdata)
          # 发送post请求,模拟登录
          response = session.post('http://activity.renren.com/livecell/ajax/clog',data=formdata)
      
          # 验证
          print(response.content.decode())
      
      
      
      if __name__ == '__main__':
      
          login()
      
  • 2.纯Python重现

    • 模拟有道翻译

      '''
      i: 人生苦短,及时行乐
      from: AUTO
      to: AUTO
      smartresult: dict
      client: fanyideskweb
      salt: r.salt
      sign: r.sign
      ts: r.ts
      bv: 7bf45b9559005ebb942310bf3549b33e
      doctype: json
      version: 2.1
      keyfrom: fanyi.web
      action: FY_BY_CLICKBUTTION
      '''
      
      import requests
      import hashlib
      import time
      import random
      import json
      
      
      class Youdao(object):
      
          # 初始化
          def __init__(self,word):
      
              self.url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
              self.headers = {
                  "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Mobile Safari/537.36",
                  "Cookie": "[email protected]; JSESSIONID=aaac4QudHCU3F6FYn3d_w; OUTFOX_SEARCH_USER_ID_NCOO=1574171141.1067092; ___rl__test__cookies=1578465296973",
                  "Referer":"http://fanyi.youdao.com/",
              }
              self.formdata = None
              self.word = word
      
          # 构建不固定的参数
          def generate_formdata(self):
              """
                  ts: r = "" + (new Date).getTime(),
                  salt: ts + parseInt(10 * Math.random(), 10),
                  sign: n.md5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj")
              }
              
              """
              # 模拟时间戳
              ts = str(int(time.time() * 1000))
              # 模拟0-9随机数
              salt = ts + str(random.randint(0,9))
              # sign
              tempstr = "fanyideskweb" + self.word + salt + "n%A-rKaT5fb[Gy?;N5@Tj"
              md5 = hashlib.md5()
              md5.update(tempstr.encode())
              sign = md5.hexdigest()
      
      
              self.formdata = {
                  "i": self.word,
                  "from": "AUTO",
                  "to": "AUTO",
                  "smartresult": "dict",
                  "client": "fanyideskweb",
                  "salt": salt,
                  "sign": sign,
                  "ts": ts,
                  "bv": "7bf45b9559005ebb942310bf3549b33e",
                  "doctype": "json",
                  "version": "2.1",
                  "keyfrom": "fanyi.web",
                  "action": "FY_BY_CLICKBUTTION",
      
              }
      
          # 发送post请求
          def get_data(self):
              response = requests.post(self.url,data=self.formdata,headers=self.headers)
              return response.content.decode()
      
          # 解析最后结果
          def parse_data(self,data):
      
              data = json.loads(data)
              return data["translateResult"][0][0]['tgt']
      
      
          # 运行
          def run(self):
              # url
              # headers
              # 构建Fromdata
              self.generate_formdata()
              # 发送请求,获取响应
              data = self.get_data()
              # 解析数据
              response_Data = self.parse_data(data)
      
              # 打印翻译结果
              print(response_Data)
      
      
      
      if __name__ == '__main__':
      
          youdao = Youdao("人生苦短,及时行乐")
          youdao.run()
      
  • 地址url去重

    • url保存集合
    • url 转换成hash保存
    • 用布隆过滤器
  • 文本内容去重

    • 编辑距离
    • simhash

你可能感兴趣的:(python,爬虫,模拟js,模拟人人网登录)