需要用到的包:
jpype
pymongo
uuid0
下载Fiddler,并配置好手机代理。
打开APP我们向下滑可以看到它在发送请求,通过Fiddler可以看到已经抓到请求了
多请求几次可以发现,只要知道signature怎么来的,我们就能模仿它的头部信息了。
这时候打开jadx,导入我们上次脱壳出来的源dex文件,按Ctrl+Shift+F
输入signature进行搜索,找到这可以发现其他的头部信息在这,点进去看下
可以发现这就是我们要的,
点击生成signature的方法跳到它的声明,可以发现它是由时间戳拼接设备号进行md5加密的
我们可以直接使用这个方法,把它打包成jar进行调用。
import java.security.MessageDigest;
/* renamed from: com.hualong.framework.b.a */
public class MySig {
/* renamed from: a */
public static String m11218a(String str) {
if (str == null) {
return null;
}
StringBuffer stringBuffer = new StringBuffer();
try {
MessageDigest instance = MessageDigest.getInstance("MD5");
instance.update(str.getBytes());
for (byte b : instance.digest()) {
stringBuffer.append(Integer.toString((b >>> 4) & 15, 16)).append(Integer.toString(b & 15, 16));
}
} catch (Exception e) {
}
return stringBuffer.toString();
}
}
把java代码保存为 xxx.java
文件,编译成class
文件 , 然后编译成jar
文件
javac MySig.java && jar cvf MySig.jar MySig.class
接下来编写Pythn代码
import time
from jpype import *
import jpype
uuid = 'IMEI867686020207104-IMSI460NNNNNNNNNNNN'
ti = str(int(time.time()))
ori_sig = uuid + "&&" + ti + "&&" + "f1190aca-d08e-4041-8666-29931cd89dde"
# 实例化一个Java虚拟机
jvmpath = getDefaultJVMPath()
# jar路径,不能有中文
jarpath = "D:/MySig/MySig.jar"
# 启动虚拟机
startJVM(jvmpath, "-ea", "-Djava.class.path=%s" % jarpath)
#print("aa", "-Djava.class.path=%s" % jarpath)
# 将类实例化对象
JDClass = JClass("MySig")
jd = JDClass()
# 调用m11218a方法
encry_sig = jd.get_sig(ori_sig)
java.lang.System.out.println(encry_sig)
#print(encry_sig)
# 关闭虚拟机,必须放在代码最后
shutdownJVM()
执行Python看下结果
接下来仿造请求头进行抓取
import requests
import time
from jpype import *
import jpype
import pymongo
import uuid0
# mongodb
MONGO_URI = 'localhost'
MONGO_DB = 'YinLiBo'
client = pymongo.MongoClient(MONGO_URI)
db = client[MONGO_DB]
def get_page(page):
"""翻页接口"""
uuid,ti,signature = getsig()
headers = {
'sys': 'Android',
'sysVersion': '6.0.1',
'appVersion': '8.2',
'appVersionCode': '54',
'udid': uuid,
'clientType': 'android',
'timestamp': ti,
'signature': str(signature),
'Host': 'app.suzhou-news.cn',
'Connection': 'Keep-Alive',
'Accept-Encoding': 'gzip',
'User-Agent': 'okhttp/3.9.0'
}
#print(headers)
url = 'https://app.suzhou-news.cn/api/v1/appNews/getBannerNewsList7?page={}&bannerID=11'.format(str(page))
response = requests.get(url, headers=headers)
if response.status_code == 200:
#print(response.text)
json = response.json()
for item in json.get('info'):
# print(item)
id = item.get('id')
result = parse_html(headers, id)
for i in result:
# print(i)
save_to_mongo(i)
def parse_html(headers, id):
"""获取详细文章页面"""
uuid,ti,signature = getsig()
url = 'https://app.suzhou-news.cn/api/v1/appNews/getNewDetail?udid={}&id={}'.format(headers['udid'], id)
# print(url)
response = requests.get(url, headers=headers)
if response.status_code == 200:
# print(response.text)
json = response.json().get('info')
yield {
'id': json.get('id'),
#'url': url,
'created_at': json.get('created_at'),
'title': json.get('title'),
'read_contents': json.get('read_contents')
}
def getsig():
"""生成signature参数,并返回uuid,ti,encry_sig"""
try:
uuid = str(uuid0.generate())
ti = str(int(time.time()))
ori_sig = uuid + "&&" + ti + "&&" + "f1190aca-d08e-4041-8666-29931cd89dde"
# 将类实例化对象
JDClass = JClass("MySig")
jd = JDClass()
# 调用m11218a方法
encry_sig = jd.get_sig(ori_sig)
java.lang.System.out.println(encry_sig)
#print(encry_sig)
return uuid,ti,encry_sig
except Exception as e:
print(e)
def save_to_mongo(data):
"""将文章存到数据库"""
# 根据url的id为主键
if db[MONGO_DB].update({'id': data['id']}, {'$set': data}, True):
print('Saved to Mongo', data['title'])
else:
print('Saved to Mongo Failed', data['title'])
def run():
"""程序入口"""
try:
# 实例化一个Java虚拟机
jvmpath = getDefaultJVMPath()
# jar路径
jarpath = "D:/MySig/MySig.jar"
# 应该是启动虚拟机
startJVM(jvmpath, "-ea", "-Djava.class.path=%s" % jarpath)
#print("aa", "-Djava.class.path=%s" % jarpath)
for i in range(1, 100):
get_page(i)
except Exception as e:
print(e)
if __name__ == "__main__":
run()
# 关闭虚拟机,必须放在代码最后
shutdownJVM()
运行脚本看下结果。
整个抓取过程就是这样。