前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >吱口令生成淘宝BP抢购链接

吱口令生成淘宝BP抢购链接

作者头像
小锋学长生活大爆炸
发布2020-11-12 11:26:29
2.2K0
发布2020-11-12 11:26:29
举报

BP链接:通俗一些就是将你需要购买产品的规格全部放到一个链接里,点击这个链接之后,能直接跳转到提交订单界面,省去了选择参数的过程。

主代码

tool.py

代码语言:javascript
复制
# 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))

待解决问题:

代码语言:javascript
复制
getGoodsProp函数中访问淘宝的https链接,经常报HTTPSConnectionPool错

附录

笔记:https://cloud.tencent.com/developer/article/1739063

userController.java

代码语言:javascript
复制
@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

代码语言:javascript
复制
@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

代码语言:javascript
复制
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测试页

代码语言:javascript
复制
<!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>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 主代码
    • tool.py
      • 待解决问题:
      • 附录
        • userController.java
          • userService.java
            • 不带css的HTML测试页
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档