您现在的位置是: 网站首页> 学习笔记> JS逆向 JS逆向
汽车之家js逆向,css反爬
2022-08-03 [JS逆向] [css反爬] 7647人已围观
今天看了一下汽车之家,记录一下详情页的CSS反爬分析。 url:https://car.autohome.com.cn/config/series/6261.html
先记录一下大概情况与获取数据方法,再上代码。
1.响应的样子;
正常请求响应的内容未经过渲染,数据放在script标签里的js变量中,如图: config变量中放的就是当前车型各版本的配置数据; 细心一点就可以看到,这些数据中词不完整,且大量充斥着\<span>标签, 每一个标签中都带一个class属性,如hs_kw41_configNl;
这个span标签在渲染后呈现给我们的就是响应中缺失的词汇。 那么我们目标就明确了就是还原span标签在当前位置表示的词汇或字符。
2.还原方法;
首先肯定是全局搜span标签的class属性hs_kw41_configNl,看看有没有对应的样式。 明显是搜不到的,然后我们把hs_kw41_configNl拆开搜一下,比如搜"_config"会搜到 拼接hs_kw41_configNl的类似代码:
function $GetClassName$ ($index$) { return '.hs_kw' + $index$ + '_configNl'; }
打个script断点大概跑一下,就会发现有代码在生成词汇数组,而数组中的索引index对应的就样式名hs_kw41_configNl中kw41的41; 把生成数组的js代码扣出来直接生成词汇映射表,根据样式名hs_kw41_configNl中的数值取值批量替换即可还原。
因为这个映射表是动态生成的,每次都不一样,所以我们也动态扣js代码, js代码就在响应中,与数据一同返回的, 一共有3段js代码,分别为生成_baike、_config、_option相对应的映射表。 比较偷懒的方法就是整段整段的扣出来,然后稍微补一些环境; 补的环境比较简单,如下即可:
window = global;
window.ruleDict = [];
document = {
createElement:function (){
return {};
},
getElementsByTagName: function (){
return [
{
appendChild: function (){}
},
]
},
};
下面贴代码,删了少量代码,避免可能造成的麻烦,有需要的可以自行补一下,就删了几行。
import json
import requests
import re
import execjs
url = "https://car.autohome.com.cn/config/series/6261.html#pvareaid=102189"
payload = {}
headers = {
'authority': 'car.autohome.com.cn',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'accept-language': 'zh-CN,zh;q=0.9',
'cache-control': 'no-cache',
'pragma': 'no-cache',
'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'none',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
}
response = requests.request("GET", url, headers=headers, data=payload)
# 取出生成字典映射关系的js
jscode = re.findall('<script>\(function\(.*?\(document\);</script>?', response.text)
baike_dict_code = ''
config_dict_code = ''
option_dict_code = ''
for _jscode in jscode:
if re.search("'.hs_kw'\s?\+\s?\$index\$\s?\+\s?'_baike\w+';", _jscode):
baike_dict_code = _jscode.replace('<script>', '').replace('</script>', '')
elif re.search("'.hs_kw'\s?\+\s?\$index\$\s?\+\s?'_config\w+';", _jscode):
config_dict_code = _jscode.replace('<script>', '').replace('</script>', '')
elif re.search("'.hs_kw'\s?\+\s?\$index\$\s?\+\s?'_option\w+';", _jscode):
option_dict_code = _jscode.replace('<script>', '').replace('</script>', '')
# js代码处理
env_code = """
window = global;
window.ruleDict = [];
document = {
createElement:function (){
return {};
},
getElementsByTagName: function (){
return [
{
appendChild: function (){}
},
]
},
};
function get_dict(){
return window.ruleDict
}
"""
to_replace_code = "替换js代码中生成数组的逻辑,自己定个变量window.ruleDict,把生成的结果赋给它直接导出"
raw_replace_code = re.search("正则找数组生成的代码块", baike_dict_code).group(1)
baike_dict_code = env_code + baike_dict_code.replace(raw_replace_code, to_replace_code)
raw_replace_code = re.search("正则找数组生成的代码块", config_dict_code).group(1)
config_dict_code = env_code + config_dict_code.replace(raw_replace_code, to_replace_code)
raw_replace_code = re.search("正则找数组生成的代码块", option_dict_code).group(1)
option_dict_code = env_code + option_dict_code.replace(raw_replace_code, to_replace_code)
# 获取内容替换映射表并转换为映射字典
ctx = execjs.compile(baike_dict_code)
baike_dict = ctx.call('get_dict')
baike_dict = {'{}'.format(idx): val for idx, val in enumerate(baike_dict)}
ctx = execjs.compile(config_dict_code)
config_dict = ctx.call('get_dict')
config_dict = {'{}'.format(idx): val for idx, val in enumerate(config_dict)}
ctx = execjs.compile(option_dict_code)
option_dict = ctx.call('get_dict')
option_dict = {'{}'.format(idx): val for idx, val in enumerate(option_dict)}
detail_raw = re.search('var config = (\{.*\});', response.text).group(1)
detail_replace_list = list(set(re.findall("<span class='hs_kw\d+_config\w+'></span>", detail_raw)))
for replace_str in detail_replace_list:
detail_raw = detail_raw.replace(replace_str, config_dict.get(re.search('kw(\d+)', replace_str).group(1)))
detail_json = json.loads(detail_raw)
print(baike_dict, '\n', config_dict, '\n', option_dict)
上一篇:维普期刊 瑞数5代js逆向分析
相关文章
文章评论
暂无评论添加评论
点击排行
本栏推荐
标签云
热评文章
- django使用qq邮箱发送邮件
- mysql8设置数据库远程连接
- pip修改下载源为国内源
- win10看不到win7共享的文件夹的解决方法
- SQLyog连接 Mysql 8.0.11 报error no.1251- Client does not support authentic...
- 使用Oracel Net Nanager配置Oracle数据库远程访问
- 将anaconda的下载源切换为国内的源
- Python+selenium+firefox设置代理IP
- selenium+firefox+js实现动态设置firefox浏览器代理IP
- scrapy文件下载(高新技术企业认定网)
- Python调用JS代码
- Chrome浏览器的overrides的使用
站点信息
- 建站时间:2021-01-01
- 网站程序:Django 3.1.2
- 文章统计:53篇
- 文章评论:36条
- 统计数据: