接上篇。
仔细查看后,发现其实主搜接口和店铺全部商品接口除了参数不同以外是同一个api,抓包即可获取相应接口的参数,同样也是需要 9.x 版本的x-sign和x-miniwua。
关键词搜索接口测试:
# -*- coding: utf-8 -*-
import time
from typing import Dict
import requests
import json
from urllib.parse import quote, unquote
def dict_encode(param_dict):
return json.dumps(param_dict, separators=(',', ':'))
class TBBaseClass():
xsign_url = "xxxxxx" # 测试链接,如需测试,请联系QQ获取,下方图片获取。
serverg = "tb910"
servera = "tbxsign"
def random_lat_lng(self):
return {"lng": "0", "lat": "0"}
def random_device_info(self):
device_info = {
"user-agent": 'Dalvik/2.1.0 (Linux; U; Android 8.1.0; Xiaomi 8 Build/OPM1.171019.011)',
"appKey": "21646297",
"utdid": 'xxxxxxxxxxxx', # search接口成功率貌似和这个有关
"ttid": "1628000524142@taobao_android_9.1.0",
}
return device_info
def random_user_cookie(self):
cookies = ""
cookies = {i.split("=")[0]: i.split("=")[1] for i in cookies.split("; ")}
return cookies
def get_xsign(self, params):
params["group"] = self.serverg
params["action"] = self.servera
try:
response = requests.post(
self.xsign_url,
json=params,
verify=False,
timeout=3
)
result = response.json()["data"]
if "x-sign" not in result.keys():
print({'error': f'调用x-sign接口失败., result: {result}'})
return None
return result
except Exception as e:
import traceback
traceback.print_exc()
print({'error': f'调用x-sign接口异常. {e}'})
return None
@staticmethod
def get_header(params, x_sign_data):
headers = {
"x-features": params.get("x-features"),
"x-pv": "6.3",
"x-sgext": "923",
"x-location": ",".join([params.get("lng"), params.get("lat")]),
"user-agent": params.get("user-agent"), # quote(params.get("user-agent"), safe="+"),
"x-ttid": params.get("ttid"),
"x-appkey": params.get("appKey"),
"x-devid": params.get("deviceId"),
"x-utdid": params.get("utdid"),
"x-t": params.get("timestamp")[:10],
"x-uid": params.get("uid"),
"x-sid": params.get("sid"),
"x-umt": quote(x_sign_data.get("x-umt"), safe=''),
"x-mini-wua": quote(x_sign_data.get("x-mini-wua"), safe=''),
"x-sign": quote(x_sign_data.get("x-sign"), safe=''),
'x-bx-version': '6.4.11',
# 'f-refer': 'mtop',
# 'x-app-ver': '9.1.0',
'user-agent': 'Dalvik/2.1.0 (Linux; U; Android 8.1.0; Xiaomi 8 Build/OPM1.171019.011)',
'Host': 'guide-acs.m.taobao.com',
}
return headers
def get_x_sign_data(self, params):
sign_params = {
"deviceId": params.get("deviceId"),
"appKey": params.get("appKey"),
"extdata": params.get("extdata"),
"utdid": params.get("utdid"),
"x-features": params.get("x-features"),
"ttid": params.get("ttid"),
"v": params.get("v"),
"sid": params.get("sid"),
"t": params.get("timestamp")[:10],
"api": params.get("api"),
"data": params.get("data"),
"uid": params.get("uid"),
"lng": params.get("lng"),
"lat": params.get("lat"),
"pageName": params.get("pageName"),
"pageId": params.get("pageId"),
}
x_sign_data = self.get_xsign(sign_params)
return x_sign_data
@staticmethod
def prepare_params(features, v, api, page_name, page_id, data, device_info, lat_lng_info, user_cookie) -> Dict:
timestamp = str(int(time.time() * 1000000))
sid = user_cookie.get("cookie2", "")
uid = user_cookie.get("unb", "")
params = {
"x-features": features,
"v": v,
"api": api,
"pageName": page_name,
"pageId": page_id,
"deviceId": device_info.get("deviceId"),
"appKey": device_info.get("appKey"),
"extdata": device_info.get("extdata"),
"utdid": device_info.get("utdid"),
"ttid": device_info.get("ttid"),
"lng": lat_lng_info.get("lng"),
"lat": lat_lng_info.get("lat"),
"sid": sid,
"uid": uid,
"data": data,
"timestamp": timestamp,
}
return params
def get_search_data(self, keword, page):
data = dict_encode({
'LBS': '{"SG_TMCS_1H_DS":"{\\"stores\\":[]}","SG_TMCS_FRESH_MARKET":"{\\"stores\\":[]}","TB":"{\\"stores\\":[{\\"code\\":\\"330408471\\",\\"bizType\\":\\"2\\",\\"type\\":\\"4\\"}]}","TMALL_MARKET_B2C":"{\\"stores\\":[]}","TMALL_MARKET_O2O":"{\\"stores\\":[{\\"code\\":\\"570945479\\",\\"bizType\\":\\"DELIVERY_TIME_ONE_HOUR\\",\\"type\\":\\"CHOOSE_ADDR\\"},{\\"code\\":\\"238594195\\",\\"bizType\\":\\"DELIVERY_TIME_HALF_DAY\\",\\"type\\":\\"CHOOSE_ADDR\\"},{\\"code\\":\\"430827236\\",\\"bizType\\":\\"DELIVERY_TIME_ONE_DAY\\",\\"type\\":\\"CHOOSE_ADDR\\"},{\\"code\\":\\"404522199\\",\\"bizType\\":\\"DELIVERY_TIME_ONE_DAY\\",\\"type\\":\\"CHOOSE_ADDR\\"}]}"}',
'URL_REFERER_ORIGIN': 'https://s.m.taobao.com/h5entry?utparam={"ranger_buckets_native":"tsp2267_22312_normaluser01"}&spm=a2141.1.searchbar.searchbox&scm=1007.home_topbar.searchbox.d&_navigation_params={"needdismiss":"0","animated":"0","needpoptoroot":"0"}',
'_navigation_params': '{"needdismiss":"0","animated":"0","needpoptoroot":"0"}',
'ad_type': '1.0',
'apptimestamp': f'1621847395',
'areaCode': 'CN',
'brand': 'XiaoMi',
'countryNum': '156',
'device': 'Xiaomi 8',
'editionCode': 'CN',
'filterEmpty': 'true',
'filterUnused': 'true',
'from': 'nt_history',
'homePageVersion': 'v6',
'imei': '',
'imsi': '',
'index': '0',
'info': 'wifi',
'itemfields': 'commentCount,newDsr',
'jarvisDisable': 'true',
'layeredSrp': 'true',
'n': '10',
'needTabs': 'true',
'network': 'wifi',
'new_shopstar': 'true',
'page': f'{page}',
'q': f'{keword}',
'rainbow': '14070,13832,11837,13104,14957,13277,12702',
'referrer': 'com.taobao.taobao',
'schemaType': 'all',
'scm': '1007.home_topbar.searchbox.d',
'searchFramework': 'true',
'search_action': 'initiative',
'search_wap_mall': 'false',
'setting_on': 'imgBanners,userdoc,tbcode,pricerange,localshop,smartTips,firstCat,dropbox,realsale,insertTexts,tabs',
'showspu': 'true',
'sort': '_coefp',
'spm': 'a2141.1.searchbar.searchbox',
'sputips': 'on',
'style': 'list',
'subtype': '',
'sugg': '_0_1',
'sversion': '8.0',
'ttid': '1628000524142@taobao_android_9.1.0',
'utd_id': 'xxxxxxxxx', # search接口成功率貌似和这个有关
'utparam': dict_encode({"ranger_buckets_native":"tsp2267_22312_normaluser01"}),
'vm': 'nw'
})
# print(data1 == data)
return data
def get_search_params(self, keyword, page):
features = "27"
api = "mtop.taobao.wsearch.appsearch"
v = "1.0"
page_name = "com.taobao.search.sf.MainSearchResultActivity"
page_id = "http%3A%2F%2Fs.m.taobao.com%2Fsearch.htm" # "http://s.m.taobao.com/search.htm"
api_url = f"http://trade-acs.m.taobao.com/gw/{api}/{v}/"
lat_lng_info = self.random_lat_lng()
device_info = self.random_device_info()
user_cookie = {}
data = self.get_search_data(keyword, page)
params = self.prepare_params(features, v, api, page_name, page_id, data, device_info, lat_lng_info, user_cookie)
x_sign_data = self.get_x_sign_data(params)
params["user-agent"] = device_info["user-agent"]
headers = self.get_header(params, x_sign_data)
return api_url, data, headers, user_cookie
def test_search_data(self, keyword, page):
api_url, data, headers, cookie = self.get_search_params(keyword, page)
params = {"data": data}
try:
response = requests.get(api_url, params=params, headers=headers, cookies=cookie, proxies=get_proxy(), timeout=3)
except:
return None
return response
obj = TBBaseClass()
res = obj.test_search_data("李宁运动鞋", 1)
print(res.status_code, res.text)
搜索关键词 "李宁运动鞋",结果如下: