目录
BP链接:通俗一些就是将你需要购买产品的规格全部放到一个链接里,点击这个链接之后,能直接跳转到提交订单界面,省去了选择参数的过程。
主代码
tool.py
# coding:utf-8
import requests
import re
import json
from bs4 import BeautifulSoup
from sys import argv
import io
import sys
import time
import random
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
from requests.packages import urllib3
urllib3.disable_warnings()
# 分隔符
SEPARATOR = '@#$%'
requests.DEFAULT_RETRIES = 5
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
'Accept': '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
'cache-control': 'no-cache',
'sec-ch-ua': '"Chromium";v="86", "\"Not\\A;Brand";v="99", "Google Chrome";v="86"',
'sec-ch-ua-mobile': '?0',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'same-origin',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'pragma': 'no-cache',
}
def getRedirUrl(share_msg):
share_url = re.findall(r'https://[^\s]+', share_msg)[0]
# 短链接获取真实链接
html = requests.get(share_url, headers=headers, allow_redirects=False)
real_url = re.findall("var url = '(.*?)'", html.text)
if len(real_url) > 0:
# 真实链接获取重定向后的链接
real_url = real_url[0]
real_url_tail = real_url.split('.htm?')[1]
id = real_url.split('.htm?')[0].split('/')[-1][1:]
redirect_url = r'https://detail.tmall.com/item.htm?id={}'.format(id)
return id, redirect_url
else:
return None, None
def getGoodsProp(url):
if url == None:
return None, None
# 获取商品页面内容
html = requests.get(url, headers=headers, verify=False)
# 获取商品属性
soup = BeautifulSoup(html.text, 'lxml')
tb_sku = soup.find(class_='tb-sku')
tm_sale_prop = tb_sku.find_all(name='dl', class_='tm-sale-prop')
prop = []
temp = []
for i in range(len(tm_sale_prop)):
item = tm_sale_prop[i]
li = item.find_all(name='li')
for l in li:
data_value = l['data-value']
tilte = l.getText().strip()
temp.append(tilte+SEPARATOR+data_value)
prop.append(temp.copy())
temp.clear()
# 获取商品所有类别的skuid
goods_content = re.findall(r'{"valItemInfo":(.*?}])', html.text)
skuList = {}
if len(goods_content) > 0:
goods_content = goods_content[0] + "}"
# print(goods_content)
goods_dict = json.loads(goods_content)
skuList = goods_dict["skuList"]
return prop, skuList
def chooseGoodsProp(props):
cnt1 = 1
for prop in props:
print(">> 属性: "+str(cnt1))
cnt1 += 1
cnt2 = 1
for p in prop:
print(str(cnt2)+": "+p)
cnt2 += 1
print()
user = input(">> 请选择属性,若有多个属性请以空格分割(如'1 2'): ").strip().split(' ')
res = ""
for i in range(len(props)):
res = res + props[i][int(user[i])-1].split(SEPARATOR)[1] + ";"
return res
def listGoodsProp(props):
cnt1 = 1
for prop in props:
print(">> 属性: "+str(cnt1))
cnt1 += 1
cnt2 = 1
for p in prop:
print(str(cnt2)+": "+p)
cnt2 += 1
print()
def chooseGoodsProp_spring(props, user):
user = user.strip().split(',')
res = ""
for i in range(len(props)):
res = res + props[i][int(user[i])-1].split(SEPARATOR)[1] + ";"
return res
def getSkuid(choose, skuList):
for item in skuList:
if choose == item.get('pvs') + ";":
return item.get('skuId')
return None
def getBpUrl(itemId, skuId):
bp_url = r'https://h5.m.taobao.com/cart/order.html?itemId={}&_input_charset=utf-8&buyNow=true&v=0&skuId={}'.format(itemId, skuId)
return bp_url
def main():
share_msg = input("输入淘宝商品吱口令: ")
# 从吱口令获取商品id和真实链接
itemId, redirect_url = getRedirUrl(share_msg)
print("itemId: "+itemId)
print("redirect_url: "+redirect_url)
# 获取商品属性
prop, skuList = getGoodsProp(redirect_url)
print("skuList: " + str(skuList))
# 用户选择属性
choose = chooseGoodsProp(prop)
# 获取属性对应的skuid
skuId = getSkuid(choose, skuList)
print("skuId: "+str(skuId))
bp_url = getBpUrl(itemId, skuId)
print("bp链接: "+bp_url)
# resulPrint.clear()
# resulPrint["itemId"] = itemId
# resulPrint["redirect_url"] = redirect_url
# resulPrint["prop"] = prop
# resulPrint["skuList"] = skuList
# resulPrint["bp"] = bp_url
# print(json.dumps(resulPrint))
resulPrint = {}
def spring():
# print("Python Interface")
mode = argv[1]
if mode == '1':
share_msg = argv[2]
# 从吱口令获取商品id和真实链接
itemId, redirect_url = getRedirUrl(share_msg)
# print("itemId: "+itemId)
# print("redirect_url: "+redirect_url)
# 获取商品属性
retry = 0
while True:
try:
prop, skuList = getGoodsProp(redirect_url)
break
except Exception as e:
if retry >= 5:
raise Exception("淘宝访问超时")
else:
retry += 1
time.sleep(random.randint(1, 4))
# prop, skuList = getGoodsProp(redirect_url)
# print("prop: " + str(prop))
# print("skuList: " + str(skuList))
resulPrint.clear()
resulPrint["itemId"] = itemId
resulPrint["redirect_url"] = redirect_url
resulPrint["prop"] = prop
resulPrint["skuList"] = skuList
print(json.dumps(resulPrint))
elif mode == '2':
itemId = argv[2]
redirect_url = argv[3]
user = argv[4]
# 获取商品属性
retry = 0
while True:
try:
prop, skuList = getGoodsProp(redirect_url)
break
except Exception as e:
if retry >= 5:
raise Exception("淘宝访问超时")
else:
retry += 1
time.sleep(random.randint(1, 4))
# 用户选择属性
choose = chooseGoodsProp_spring(prop, user)
# 获取属性对应的skuid
skuId = getSkuid(choose, skuList)
# print("skuId: "+skuId)
bp_url = getBpUrl(itemId, skuId)
# print("bp链接: "+bp_url)
resulPrint.clear()
resulPrint["bp"] = bp_url
print(json.dumps(resulPrint))
if __name__ == '__main__':
main()
# try:
# spring()
# except Exception as e:
# # print(e)
# resulPrint.clear()
# resulPrint["err"] = 500
# resulPrint["errmsg"] = str(e)
# print(json.dumps(resulPrint))
待解决问题:
getGoodsProp函数中访问淘宝的https链接,经常报HTTPSConnectionPool错
附录
笔记:SpringBoot代码片段,方便自己查看[持续添加]_小锋学长生活大爆炸-CSDN博客
userController.java
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/")
public String index() {
return "hello";
}
@RequestMapping("/getRedirUrl")
public Result getRedirUrl(String shareMsg) {
System.out.println(">> getRedirUrl");
return userService.getRedirUrl(shareMsg);
}
@RequestMapping("/getGoodsProp")
public Result getGoodsProp(String shareMsg) {
System.out.println(">> getGoodsProp");
return userService.getGoodsProp(shareMsg);
}
@RequestMapping("/getBpUrl")
public Result getBpUrl(String itemId, String url, String user) {
System.out.println(">> getBpUrl");
return userService.getBpUrl(itemId, url, user);
}
@RequestMapping("/test")
public Result test() {
System.out.println(">> test");
String str = "{\"itemId\": \"620278928010\", \"redirect_url\": \"https://detail.tmall.com/item.htm?id=620278928010&price=99-269&sourceType=item&sourceType=item&suid=b1b5b243-35c5-4fc5-a9c3-749e47bb012f&shareUniqueId=4948880474&ut_sk=1.XXsflQSA7sEDABWrN6TsGosi_21646297_1604370916299.Copy.1&un=4c4cd55ba530f81c4c6e4bed9157ce66&share_crt_v=1&spm=a2159r.13376460.0.0&sp_tk=U2FBbGNRTDRoTnE=&cpp=1&shareurl=true&short_name=h.4dacF0M&bxsign=scd6Cbz98QmcArDdLbgBZndmCgDDaXinqw3awZ6h3gfbCCnNQU5dPd_JaAnQOlsnPOzrRElx9xVqODJq1NHO2x270LHwIfabKtrPjV8DXZUpMU\", \"prop\": [[\"\\u5c0f\\u7c73\\u624b\\u73af5@#$%1627207:3232483\", \"\\u5c0f\\u7c73\\u624b\\u73af5\\u3010\\u987a\\u4e30\\u5feb\\u9012\\u3011@#$%1627207:3232484\", \"\\u5c0f\\u7c73\\u624b\\u73af5NFC@#$%1627207:60092\", \"\\u5c0f\\u7c73\\u624b\\u73af5NFC\\u3010\\u987a\\u4e30\\u5feb\\u9012\\u3011@#$%1627207:3232482\", \"\\u2605\\u2605\\u2605\\u5c0f\\u7c73\\u624b\\u73af 4 NFC \\u2605\\u2605\\u2605@#$%1627207:28332\", \"\\u2605\\u2605\\u2605\\u5c0f\\u7c73\\u624b\\u73af 4 \\u2605\\u2605\\u2605@#$%1627207:3232478\", \"\\u5c0f\\u7c73\\u624b\\u73af3 NFC \\uff08\\u7ecf\\u5178\\u8001\\u6b3e\\uff09@#$%1627207:3232481\"]], \"skuList\": [{\"names\": \"\\u519b\\u7eff\\u8272 \", \"pvs\": \"1627207:3232483\", \"skuId\": \"4556051290889\"}, {\"names\": \"\\u5929\\u84dd\\u8272 \", \"pvs\": \"1627207:3232484\", \"skuId\": \"4568862370599\"}, {\"names\": \"\\u6d45\\u9ec4\\u8272 \", \"pvs\": \"1627207:60092\", \"skuId\": \"4556051290890\"}, {\"names\": \"\\u6df1\\u5361\\u5176\\u5e03\\u8272 \", \"pvs\": \"1627207:3232482\", \"skuId\": \"4398756481400\"}, {\"names\": \"\\u6d45\\u7070\\u8272 \", \"pvs\": \"1627207:28332\", \"skuId\": \"4398756481399\"}, {\"names\": \"\\u6df1\\u7070\\u8272 \", \"pvs\": \"1627207:3232478\", \"skuId\": \"4583347495714\"}, {\"names\": \"\\u5de7\\u514b\\u529b\\u8272 \", \"pvs\": \"1627207:3232481\", \"skuId\": \"4600967691345\"}]}";
return new Result().ok(str);
}
}
userService.java
@Service
public class UserService {
public Result getRedirUrl(String shareMsg) {
System.out.println(shareMsg);
String itemId = "id", redirectUrl = "url";
Map<String, Object> map = new HashMap<>(2);
map.put("itemId", itemId);
map.put("redirect_url", redirectUrl);
Map<String, Object> res = new HashMap<>(1);
res.put("msg", map);
return new Result().ok(res);
}
public Result getGoodsProp(String shareMsg) {
StringBuilder successSb = new StringBuilder();
StringBuilder errorSb = new StringBuilder();
try {
String[] args = new String[] {"python", "C:\\Users\\10617\\Desktop\\tool.py", "1", shareMsg};
Process process = Runtime.getRuntime().exec(args);
BufferedReader successMsg = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
BufferedReader errorMsg = new BufferedReader(new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8));
String line;
while ((line=successMsg.readLine())!=null) {
System.out.println(line);
successSb.append(line);
}
successMsg.close();
errorMsg.close();
process.waitFor();
}catch (Exception e){
e.printStackTrace();
return new Result().error();
}
return new Result().ok(successSb.toString());
}
public Result getBpUrl(String itemId, String url, String user) {
StringBuilder sb = new StringBuilder();
try {
String[] args = new String[] {"python", "C:\\Users\\10617\\Desktop\\tool.py", "2", itemId, url, user};
Process process = Runtime.getRuntime().exec(args);
BufferedReader successMsg = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
BufferedReader errorMsg = new BufferedReader(new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8));
String line;
while ((line=successMsg.readLine())!=null) {
System.out.println(line);
sb.append(line);
}
// while ((line=errorMsg.readLine())!=null) {
// System.out.println(line);
// }
successMsg.close();
errorMsg.close();
process.waitFor();
}catch (Exception e){
e.printStackTrace();
return new Result().error();
}
return new Result().ok(sb.toString());
}
}
Result.java
public class Result extends HashMap<String, Object> {
public Result() {}
public Result error(String msg) {
Result r = new Result();
r.put("code", 500);
r.put("msg", msg);
return r;
}
public Result error() {
Result r = new Result();
r.put("code", 500);
r.put("msg", "未知错误");
return r;
}
public Result ok() {
Result r = new Result();
r.put("code", 0);
r.put("msg", "操作成功");
return r;
}
public Result ok(String msg) {
Result r = new Result();
r.put("code", 0);
r.put("msg", msg);
return r;
}
public Result ok(List<Map<String, Object>> list) {
Result r = new Result();
r.put("code", 0);
r.put("msg", list);
return r;
}
public Result ok(Map<String, Object> map) {
Result r = new Result();
r.put("code", 0);
r.putAll(map);
return r;
}
}
不带css的HTML测试页
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</head>
<body>
<button id="reload" style="display: block;">重置</button>
<label>吱口令:</label>
<br />
<textarea id="shareMsg" name="shareMsg"></textarea>
<button id="submit_1" style="display: block;">提交1</button>
<br />
<hr />
<div id="goodsprop" style="display: none;">
<div id="propbox"> </div>
<div>
<label>商品链接</label>
<input type="text" id="redirurl"/>
</div>
<div>
<label>商品ID</label>
<input type="text" id="itemId"/>
</div>
<button id="submit_2" style="display: block;">提交2</button>
</div>
<br />
<hr />
<div id="bpurlbox" style="display: none;">
<label>BP链接</label>
<input type="text" id="bpurl"/>
</div>
</body>
<script type="text/javascript">
// https://www.w3school.com.cn/jquery/ajax_ajax.asp
// https://www.w3school.com.cn/jquery/ajax_get.asp
// https://blog.csdn.net/assiduous_me/article/details/90108590
var targetUrl = "http://192.168.1.107:8080/";//"http://127.0.0.1:8080/";
$(document).ready(function(){
$("#submit_1").click(function(){
// 删除所有子元素
$("#propbox").empty();
var url = targetUrl+"getGoodsProp?shareMsg="+$("#shareMsg").val();
var url_test = targetUrl+"test";
$.ajax({
type: "GET",
url: url, // 测试时用:url_test
data: {shareMsg: $("#shareMsg").val()},
dataType: "json",
success: function(response, status) {
if(status == "success") {
var code = response.code
if(code==0) {
var msg = JSON.parse(response.msg)
// 如果存在
if(msg.err) {
alert("接口调用超时,可稍后再试: "+msg.errmsg);
console.log(msg.errmsg);
}else {
// 禁用按钮1
$("#submit_1").attr("disabled", true);
var itemId = msg.itemId
var redirect_url = msg.redirect_url
var prop = msg.prop
var skuList = msg.skuList
// 显示下拉选择框
for(var outer=0; outer<prop.length; outer++) {
$("#propbox").append("<select id='prop"+outer+"'></select><br />");
for(var inner=0; inner<prop[outer].length; inner++) {
// console.log(outer + " " + inner)
$("#prop"+outer).append("<option value="+(inner+1)+">"+prop[outer][inner].split("@#$%")[0]+"</option>");
}
}
// 显示重定向URL
$("#itemId").val(itemId);
// 显示重定向URL
$("#redirurl").val(redirect_url);
console.log(skuList.length)
// 显示元素
$("#goodsprop").show();
}
}else {
console.log("code: "+code+"\n")
}
}else {
alert("错误");
}
}
});
});
});
$(document).ready(function(){
$("#submit_2").click(function(){
$("#bpurl").val("");
var user = "";
for(var i=0; i<$("#propbox").children().length/2; i++) {
user = user + $("#prop"+i).val() + ",";
}
// 去掉最后多余的逗号
// console.log($("#propbox").children().length);
user = user.substring(0, user.length-1);
// console.log($("#itemId").val()+" "+$("#redirurl").val()+" "+user)
var url = targetUrl+"getBpUrl";
var url_test = targetUrl+"test";
$.ajax({
type: "GET",
url: url,
data: {
itemId: $("#itemId").val(),
url: $("#redirurl").val(),
user: user
},
dataType: "json",
success: function(response, status) {
if(status == "success") {
console.log(response);
var code = response.code;
if(code == 0) {
var msg = JSON.parse(response.msg)
if(msg.err) {
alert("接口调用错误,可稍后再试:"+msg.errmsg);
console.log(msg.errmsg);
}else {
// 启用按钮1
$("#submit_1").attr("disabled", false);
console.log("成功");
alert("成功!");
var bp = msg.bp;
$("#bpurl").val(bp);
$("#bpurlbox").show();
}
}else {
console.log("code: "+code+"\n")
}
}else {
alert("错误");
}
}
});
});
});
$(document).ready(function(){
$("#reload").click(function(){
window.location.reload();
});
});
</script>
</html>