Python에서 JS를 호출하는 다양한 방법 요약

1. 앞에 쓰기

  크롤러라면 누구나 국내 웹이나 앱의 전반적인 보호가 매우 우수하고 웹사이트의 가치가 높을수록 이러한 측면이 강하다는 것을 알고 있습니다.

현재 웹 사이트가 아무리 작거나 약하더라도 전체적으로 어느 정도 안티 크롤링되어야 합니다.
여기에 이미지 설명 삽입

JS는 크롤링 방지에 널리 사용됩니다.다양한 JS 암호화를 반전해야 하므로 이제 크롤러 엔지니어는 기본적으로 JS를 이해해야 합니다! JS 암호화를 크래킹하는 것은 첫 번째 단계일 뿐이며, 그 다음 Python 코드에서 직접 JS를 실행하는 방법은 다음과 같습니다.Python에서 JS 코드를 실행하는 몇 가지 방법이 있습니다.

2. PyExecJS 방식

첫 번째 단계는 다음을 설치하는 것입니다.

pip3 install PyExecJS

PyExecJS는 JavaScript 코드를 실행하기 위한 공통 인터페이스를 제공하고 Node.js, PhantomJS를 포함한 여러 JavaScript 런타임 환경에서 작동할 수 있는 사용하기 쉬운 라이브러리입니다.

그런 다음 Python에서 JS 코드를 실행하기 위한 라이브러리인 import excejs를 사용하는 예는 다음과 같습니다.

md5_js = 
'''function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * 8));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * 8));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function calcMD5(s){ return binl2hex(core_md5(str2binl(s), s.length * 8));}

function md5_vm_test()
{
  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}
function cxx(a, d) {
    var e;
    a = a - 0,e = str_spl[a]
    return e;
}
function core_md5(x, len)
{

  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;
  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;
  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);

}

function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

function core_hmac_md5(key, data)
{
  var bkey = str2binl(key);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * 8);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * 8);
  return core_md5(opad.concat(hash), 512 + 128);
}

function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

function str2binl(str)
{
  var bin = Array();
  var mask = (1 << 8) - 1;
  for(var i = 0; i < str.length * 8; i += 8)
    bin[i>>5] |= (str.charCodeAt(i / 8) & mask) << (i%32);
  return bin;
}

function binl2hex(binarray)
{
  var hex_tab = 0 ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}
function binl2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += '';
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}'''
content = '加密内容'
ctx = execjs.compile(md5_js)
sk = ctx.call('hex_md5', content)

호출 의 첫 번째 매개변수 는 JS 함수의 이름이며, 실행할 JS에 매개변수가 있는 경우 매개변수 뒤에 위의 내용이 올 수 있습니다 .

3. js2py 메서드

첫 번째 단계는 다음을 설치하는 것입니다.

 pip3 install js2py

js2py는 Python용으로 특별히 설계된 라이브러리로 Python에서 JavaScript 코드를 실행할 수 있으며 비교적 완전한 JavaScript 인터프리터를 제공합니다. 클로저 및 예외 처리와 같은 보다 복잡한 JavaScript 기능을 지원합니다.

난독화되고 복잡한 JavaScript 코드를 처리할 수 있으므로 일부 리버스 엔지니어링 시나리오에 적합합니다.

그 원칙은 실행을 위해 JS 코드를 Python 코드로 직접 변환하는 것입니다. 로컬 환경을 설치하고 실행할 필요가 없으며 시작이 더 빠릅니다.

다만, 번역시 실행시간이 늘어나고, 특히 JS코드가 많은 경우 번역시 오류가 보고되는 경우가 있는데, 로컬 JS 환경을 사용하지 않기 때문에 JS처럼 헷갈리는 코드를 번역할 때 오류를 보고하기 쉬운 경우가 많습니다.

사용 예:

import js2py
js2py.eval_js('console.log( "Hello World!" )')

execute를 사용하여 JS 코드 예제를 실행합니다.

import js2py
context = js2py.EvalJs() # 实例化解析js对象
js_code = '''
var a = 10
function f(x) {return x*x}
'''
context.execute(js_code) # 调用js代码里面的函数
context.a

JS에서 직접 Python 내장 함수를 사용하는 예:

import js2py
context = js2py.EvalJs({
    
    'python_sum': sum})
context.eval('python_sum(new Array(1, 2, 3))')

sum 함수는 파이썬의 함수로 js2py에서 바로 사용할 수 있습니다.사실 js2py는 js를 파이썬 코드로 번역한 후 실행하기 때문에 이해하기 쉽습니다.물론 파이썬 함수를 직접 실행할 수도 있습니다.

JS 파일을 번역하는 방법의 예:

from example import example
js2py.translate_file('example.js', 'example.py')
example.someFunction()

위의 앞선 방법 외에도 JS 파일을 파이썬 코드로 번역한 후 호출할 수도 있는데, JS 파일을 호출할 때마다 매번 번역할 필요가 없다는 장점이 있습니다.

이제 js2py는 JavaScript6도 지원합니다. 더 많은 사용 기술에 관심이 있는 경우 공식 웹사이트로 이동하여 확인할 수 있습니다: Js2Py

4. 노드 방식

먼저 nodejs를 먼저 설치하고 subprocess를 사용하여 node subprocess를 호출하여 JS를 실행하십시오.

장점 : 속도가 빠르고 일반적으로 오류가 없음. nodejs는 크롬 브라우저와 같은 v8 엔진을 사용하기 때문에 이 방법이 위의 5가지 방법 중 가장 안정적이며, 특히 실행할 js 코드가 많을 때 node.js를 호출하는 것이 좋습니다. 곧장

단점 : Nodejs를 설치해야 하고, 다창 웹사이트나 앱의 js가 일반적으로 nodejs를 감지할 경우 js 코드를 잘 처리해야 하며, 그렇지 않으면 통과하지 못합니다.

import subprocess
# js文件最后必须有输出,我使用的是 console.log
pro = subprocess.run("node abc.js", stdout=subprocess.PIPE)
# 获得标准输出
_token = pro.stdout
# 转一下格式
token = _token.decode().strip()

5. 셀레늄법

첫 번째 단계는 다음을 설치하는 것입니다.

pip3 install selenium

Selenium은 브라우저 동작을 시뮬레이션하는 자동화된 테스트 도구입니다. 브라우저에서 JavaScript를 실행하여 웹 페이지 렌더링을 위한 일련의 작업을 구현할 수 있습니다.

여기에서 웹드라이버를 다운로드하고 크롬 브라우저 또는 다른 브라우저와 해당 웹드라이버를 설치해야 합니다.

드라이버 주소: 크롬드라이버

셀레늄 공식 웹사이트: 셀레늄

장점 : JS 코드를 파헤치는 지루하고 번거로운 일을 덜어줍니다.

단점 : 브라우저 환경 지원이 있어야 하고 실행 효율이 낮아 브라우저 환경에서 JS 코드를 실행하는 경우에만 적합하다.

일반적으로 셀레늄을 사용하는 것은 권장되지 않지만 낮은 수집 효율을 신경쓰지 않는다면 셀레늄이 좋은 선택입니다.

사용 예:

from selenium import webdriver
jsstr = '''
function add() {
    let a = 1;
    let b = 2;
    return a+b;
}'''
# 调用js
driver = webdriver.chrome()
# 异步用这个driver.execute_async_script(js)
result = driver.execute_script(jsstr)
print(result)

다음은 초기에 브라우저 User-Agent를 업데이트하기 위한 JS 호출입니다.

여기에 이미지 설명 삽입

6. PyV8 방법

PyV8은 Python에서 JavaScript 코드를 실행할 수 있는 기능을 제공하는 Google의 V8 엔진을 기반으로 하는 라이브러리입니다. V8 엔진은 고성능 자바스크립트 엔진이기 때문에 성능면에서 유리하다.

PyV8은 Python2의 pip 설치만 지원하고 python3 환경의 pip 설치를 지원하지 않습니다. 공식 웹사이트로 직접 이동하여 바이너리 파일을 다운로드하고 설치 하십시오 : PyV8

그런 다음 압축을 푼 후 PyV8.py 및 _PyV8.so를 복사하고(참고: 이 두 파일 이름이 아닌 경우 수정해야 함) 두 파일을 Python의 사이트 패키지 디렉터리(예: /usr/local/)에 복사합니다 . lib/python3.6 /사이트 패키지

사용 예:

import PyV8
ctxt = PyV8.JSContext()
# ctxt.__enter__()
ctxt.enter()
jsstr = '''
function add() {
    let a = 1;
    let b = 2;
    return a+b;
}'''
result = ctxt.eval(jsstr)
print(result)

마지막으로 비즈니스 요구 사항에 따라 위의 적절한 방법을 선택할 수 있습니다.

  자, 이제 여기 계신 모든 분들께 다시 작별 인사를 할 시간입니다. 만들기가 쉽지 않은데, 떠나기 전에 좋아요 부탁드립니다. 여러분의 지원은 제 창작의 원동력이며, 더 많은 양질의 기사를 제공할 수 있기를 바랍니다.

추천

출처blog.csdn.net/qiulin_wu/article/details/132282819