├── README.md └── wxlj_Authorization_test.py /README.md: -------------------------------------------------------------------------------- 1 | # reverse_lianjia_wxapkg 2 | 逆向链家微信小程序,解析 请求的加密方式获取数据 3 | 4 | ### 破解链家小程序中的请求加密方式: 5 | - 1、获取链家微信小程序的 .wxapkg 包文件、解开 .wxapkg 程序包 6 | - 2、了解.wxapkg文件结构 7 | - 3、查看程序逻辑,实验生成Authorization 8 | - 4、验证迭代、实现加密方式 9 | 10 | 详细破解过程见我的 知乎文章。 11 | 12 | ### Authorization 生成方式: 13 | 这里以获取二手房信息为例 14 | 15 | Url = 'https://wechat.lianjia.com/ershoufang/search?city_id=310000&condition=&query=&order=&offset=0&limit=10&sign=' 16 | 17 | Authorization = 'bGp3eGFwcDoxYmU3OThjZDg0ZWU4NzNmM2JhMzM0NTFhZTNkNWUwMA==' 18 | 19 | 加密过程 20 | 21 | 1、获取参数部分,这里为 ‘city=310000&condition=&query=&order=&offset=0&limit=10&sign=’ 22 | 23 | 2、对参数进行从大到小排序、并将key-value用等号连接起来,将所有的元素连接成为一个字符串 S 24 | 25 | 排序后: 26 | 27 | {'city_id': '310000', 'condition': '', 'limit': '10', 'offset': '0', 'order': '', 'query': '', 'sign': ''} 28 | 29 | key-value用等号连接起来,并连接所有元素: 30 | 31 | S = 'city_id=310000condition=limit=10offset=0order=query=sign=' 32 | 33 | 3、 添加后缀 "6e8566e348447383e16fdd1b233dbb49"到变量S中,获取S的MD5值。 34 | 35 | 4、为变量 S 的MD5值 添加前缀 ‘ljwxapp:’,并作base64 编码,生成为:‘bGp3eGFwcDoxYmU3OThjZDg0ZWU4NzNmM2JhMzM0NTFhZTNkNWUwMA==’的 Authorization 36 | 37 | 38 | 39 | Python 实现代码如下 40 | 41 | AUTHORIZATION_SIFFOX = "6e8566e348447383e16fdd1b233dbb49" 42 | AUTHORIZATION_PREFIX = 'ljwxapp:' 43 | 44 | def get_authorization(data): 45 | """ 46 | 获取 authorization 47 | :param data: 48 | 例子参数 49 | {'city_id': '310000', 'condition': '', 'query': '', 'order': '', 50 | 'offset': '0', 'limit': '10', 'sign': ''} 51 | :return: 52 | 例子 authorization 返回值 53 | b'bGp3eGFwcDoxYmU3OThjZDg0ZWU4NzNmM2JhMzM0NTFhZTNkNWUwMA==' 54 | """ 55 | 56 | global AUTHORIZATION_SIFFOX 57 | global AUTHORIZATION_PREFIX 58 | l = "" 59 | data_sort = dict_sort(data) 60 | l += ''.join([key + '=' + str(data_sort[key]) for key in data_sort.keys()]) 61 | l += AUTHORIZATION_SIFFOX 62 | l_md5 = hashlib.md5(l.encode()).hexdigest() 63 | authorization_source = AUTHORIZATION_PREFIX+l_md5 64 | authorization = base64.b64encode(authorization_source.encode()) 65 | 66 | return authorization.decode() 67 | 68 | 更详细的见代码部分见 [wxlj_Authorization_test.py](https://github.com/Ant-Ferry/reverse_lianjia_wxapkg/blob/master/wxlj_Authorization_test.py), 69 | 其中实现了一个 获取上海 二手房数据列表的例子。 70 | 71 | 72 | -------------------------------------------------------------------------------- /wxlj_Authorization_test.py: -------------------------------------------------------------------------------- 1 | 2 | import hashlib 3 | import base64 4 | import time 5 | import requests 6 | from urllib.parse import parse_qs, urlparse 7 | 8 | AUTHORIZATION_SIFFOX = "6e8566e348447383e16fdd1b233dbb49" 9 | AUTHORIZATION_PREFIX = 'ljwxapp:' 10 | 11 | def dict_sort(d): 12 | return {k: d[k] for k in sorted(d)} 13 | 14 | 15 | def get_authorization(data):""" 16 | 17 | 获取 authorization 18 | :param data: 19 | 例子参数 20 | {'city_id': '310000', 'condition': '', 'query': '', 'order': '', 'offset': '0', 'limit': '10', 'sign': ''} 21 | :return: 22 | 例子 authorization 返回值 23 | b'bGp3eGFwcDoxYmU3OThjZDg0ZWU4NzNmM2JhMzM0NTFhZTNkNWUwMA==' 24 | """ 25 | 26 | global AUTHORIZATION_SIFFOX 27 | global AUTHORIZATION_PREFIX 28 | l = "" 29 | data_sort = dict_sort(data) 30 | l += ''.join([key + '=' + str(data_sort[key]) for key in data_sort.keys()]) 31 | l += AUTHORIZATION_SIFFOX 32 | l_md5 = hashlib.md5(l.encode()).hexdigest() 33 | authorization_source = AUTHORIZATION_PREFIX+l_md5 34 | authorization = base64.b64encode(authorization_source.encode()) 35 | 36 | return authorization.decode() 37 | 38 | 39 | def get_house_list(url): 40 | parse = parse_qs(urlparse(url).query, keep_blank_values=True) 41 | data = {key: value[-1] for key, value in parse.items()} 42 | 43 | authorization = get_authorization(data) 44 | 45 | headers = { 46 | 'Lianjia-Uuid': '4fbaf7cccaa68133621280c523aada66', 47 | 'Wxminiapp-SDK-Version': '1.9.9', 48 | 'Lianjia-Wxminiapp-Version': '0.1', 49 | 'Authorization': '', 50 | 'Accept': '*/*', 51 | 'Lianjia-Source': 'ljwxapp', 52 | 'Time-Stamp': str(int(time.time() * 1000)), 53 | 'Accept-Language': 'zh-cn', 54 | 'Lianjia-Session': '', 55 | 'Accept-Encoding': 'gzip, deflate', 56 | 'Wx-Version': '6.6.1', 57 | 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Mobile/14G60 MicroMessenger/6.6.1 NetType/WIFI Language/zh_CN', 58 | 'Connection': 'keep-alive', 59 | 'Content-Type': 'application/json', 60 | 'OS-Version': 'ios-iOS 10.3.3', 61 | } 62 | 63 | headers['Authorization'] = authorization 64 | r = requests.get(url, headers=headers) 65 | return r.json() 66 | 67 | 68 | if __name__ in "__main__": 69 | # 获取上海 二手房数据 70 | url = 'https://wechat.lianjia.com/ershoufang/search?city_id=310000&condition=&query=&order=&offset=0&limit=10&sign=' 71 | 72 | # 读取 100条数据 73 | for p in range(0,100,10): 74 | url_1 = 'https://wechat.lianjia.com/ershoufang/search?city_id=310000&condition=&query=&order=&offset={}&limit=10&sign='.format(p) 75 | jj = get_house_list(url_1) 76 | print(jj['data']) 77 | 78 | 79 | --------------------------------------------------------------------------------