| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- # BUFF选品01脚本
- import re
- from traceback import print_tb
- import requests as req
- import time,random,numpy as np
- from datetime import datetime
- from exceptiongroup import catch
- import argparse
- import mysql.connector
- from numpy.ma.core import argsort
- from selenium.webdriver.common.devtools.v85.system_info import ProcessInfo
- import json
- class xpjb():
- def __init__(self):
- # 数据库配置
- self.host = "121.40.50.77"
- self.user = "root"
- self.password = "Root@123456"
- self.database = "ry-vue"
- # 程序执行次数
- self.total_run_count = 0
- # 入参
- self.args = None
- # 选品账号的email
- self.xpzh_email = None
- # 选品账号的email_dh
- self.xpzh_email_dh = None
- # 选品账号的cookie
- self.xpzh_cookie = None
- # 选品有效品类信息
- self.xp_category_list=[]
- # 选品品质信息
- self.xp_rarity_list=[]
- # 选品类别信息
- self.xp_quality_list=[]
- # 选品外观信息
- self.xp_exterior_list=[]
- # 选品收藏品信息
- self.xp_itemset_list=[]
- # 已检索的BUFF商品数
- self.searchedGoodsNum =0;
- #BUFF搜寻商品入参
- self.search_good_param_init = {
- 'game': 'csgo'
- }
- #BUFF搜寻商品入参数list,因为有些内容存在多个选择,检索条件采取组合模式,分批次请求,请求中加入暂停,以防锁号
- self.search_good_param_list=[]
- # buff选品接口配置
- self.goodsurl = 'https://buff.163.com/api/market/goods'
- self.my_headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36",
- "Host": "buff.163.com",
- "Referer": "https://buff.163.com/market/?game=csgo",
- "X-Requested-With": "XMLHttpRequest"
- }
- # 判断嵌套属性是否存在
- @staticmethod
- def has_nested_attribute(obj, attr_path):
- attrs = attr_path.split('.')
- try:
- for attr in attrs:
- obj = obj[attr] if isinstance(obj, dict) else getattr(obj, attr)
- return True
- except (KeyError, AttributeError):
- return False
- # 处理命令行参数
- def dealArgc(self):
- try:
- print('处理命令行参数--开始')
- # 创建解析器
- parser = argparse.ArgumentParser(description='BUFF选品脚本')
- # 添加一个位置参数,表示运行多久重新再运行 默认10秒
- parser.add_argument('--runtime', type=str,default=10, help='单次运行时间 默认10秒')
- # 添加一个位置参数,表示自动运行多少次程序,默认为10次
- parser.add_argument('--runcount', type=int,default=10, help='程序运行总次数,默认为10次')
- # 添加一个位置参数,表示每次调用BUFF接口程序运行间隔多少秒,默认为10秒
- parser.add_argument('--timeinterval', type=int,default=5, help='每次调用BUFF接口程序运行间隔多少秒,默认为10秒')
- # 添加一个位置参数,表示选品账号的手机号码
- parser.add_argument('--xp_phone', type=str ,default=17756576757, help='选品账号的手机号码,17756576757')
- # 添加一个位置参数,表示选品脚本停止条件标志,1 按照成功数量,2 按照页数和每页数量 默认为1
- parser.add_argument('--xptz_status', type=int ,default=1, help='选品脚本停止条件标志,1 按照成功数量,2 按照页数和每页数量 默认为1')
- # 添加一个位置参数,表示选品脚本停止条件标志的成功数量, 默认 200
- parser.add_argument('--xptz_success_num', type=int ,default=200, help='选品脚本停止条件标志的成功数量, 默认 200')
- # 添加一个位置参数,表示选品脚本停止条件标志的页数 默认 100
- parser.add_argument('--xptz_page_num', type=int ,default=100, help='选品脚本停止条件标志的页数 默认 100')
- # 添加一个位置参数,表示选品脚本停止条件标志的每页数量 默认 80
- parser.add_argument('--xptz_page_size', type=int ,default=80, help='选品脚本停止条件标志的每页数量 默认 80')
- # 添加一个位置参数,表示选品最低价(元)
- parser.add_argument('--xp_min_price', help='选品最低价')
- # 添加一个位置参数,表示选品最高价(元)
- parser.add_argument('--xp_max_price', help='选品最高价')
- # 添加一个位置参数,表示选品排序模式 price.asc 价格升序 price.desc 价格降序 sell_num.desc 在售数量
- parser.add_argument('--xp_sort',type=str, help='选品排序模式')
- # 解析命令行参数
- self.args = parser.parse_args()
- # 使用参数
- print(f'单次运行时间,默认10秒: {self.args.runtime}')
- print(f'自动运行多少次程序 默认10次: {self.args.runcount}')
- print(f'每次调用BUFF接口程序运行间隔多少秒 默认5秒: {self.args.timeinterval}')
- print(f'选品账号的手机号码: {self.args.xp_phone}')
- print(f'选品脚本停止条件标志: {self.args.xptz_status}')
- print(f'选品脚本停止条件标志的成功数量 默认 200: {self.args.xptz_success_num}')
- print(f'选品脚本停止条件标志的页数 默认 100: {self.args.xptz_page_num}')
- print(f'选品脚本停止条件标志的每页数量 默认 80: {self.args.xptz_page_size}')
- print(f'选品最低价: {self.args.xp_min_price}')
- print(f'选品最高价: {self.args.xp_max_price}')
- print(f'选品排序模式: {self.args.xp_sort}')
- print('处理命令行参数--成功')
- except Exception as e:
- print('处理命令行参数--失败',e)
- exit()
- # 获取选品品类信息
- def getXpCategory(self):
- print('获取选品品类信息')
- try:
- # 创建mysql连接
- conn = mysql.connector.connect(
- host=self.host,
- user=self.user,
- password=self.password,
- database=self.database
- )
- # 创建游标对象
- cursor = conn.cursor()
- # 执行SQL查询
- cursor.execute(f"select category_code from sys_category where del_flag = '0' and status = '0' ")
- # 获取所有记录列表
- results = cursor.fetchall()
- if len(results) == 0:
- print('选品品类信息不存在,请检查数据库配置')
- self.xp_category_list=[]
- for row in results:
- self.xp_category_list.append(row[0])
- # 关闭游标和连接
- cursor.close()
- conn.close()
- except Exception as e:
- print('获取选品品类信息--失败',e)
- exit()
- # 获取选品品质信息
- def getXpRarity(self):
- print('获取选品品质信息')
- try:
- # 创建mysql连接
- conn = mysql.connector.connect(
- host=self.host,
- user=self.user,
- password=self.password,
- database=self.database
- )
- # 创建游标对象
- cursor = conn.cursor()
- # 执行SQL查询
- cursor.execute(f"select quality_code from sys_quality where del_flag = '0' and quality_status = '0' ")
- # 获取所有记录列表
- results = cursor.fetchall()
- if len(results) == 0:
- print('选品品质信息不存在,请检查数据库配置')
- self.xp_rarity_list=[]
- for row in results:
- self.xp_rarity_list.append(row[0])
- # 关闭游标和连接
- cursor.close()
- conn.close()
- except Exception as e:
- print('获取选品品质信息--失败',e)
- exit()
- # 获取选品类别信息
- def getXpQuality(self):
- print('获取选品类别信息')
- try:
- # 创建mysql连接
- conn = mysql.connector.connect(
- host=self.host,
- user=self.user,
- password=self.password,
- database=self.database
- )
- # 创建游标对象
- cursor = conn.cursor()
- # 执行SQL查询
- cursor.execute(f"select type_code from sys_type where del_flag = '0' and typestatus = '0' ")
- # 获取所有记录列表
- results = cursor.fetchall()
- if len(results) == 0:
- print('选品类别信息不存在,请检查数据库配置')
- self.xp_quality_list=[]
- for row in results:
- self.xp_quality_list.append(row[0])
- # 关闭游标和连接
- cursor.close()
- conn.close()
- except Exception as e:
- print('获取选品类别信息--失败',e)
- exit()
- # 获取选品外观信息
- def getXpExterior(self):
- print('获取选品外观信息')
- try:
- # 创建mysql连接
- conn = mysql.connector.connect(
- host=self.host,
- user=self.user,
- password=self.password,
- database=self.database
- )
- # 创建游标对象
- cursor = conn.cursor()
- # 执行SQL查询
- cursor.execute(f"select appear_code from sys_appear where del_flag = '0' and appear_sta = '0' ")
- # 获取所有记录列表
- results = cursor.fetchall()
- if len(results) == 0:
- print('选品外观信息不存在,请检查数据库配置')
- self.xp_exterior_list=[]
- for row in results:
- self.xp_exterior_list.append(row[0])
- # 关闭游标和连接
- cursor.close()
- conn.close()
- except Exception as e:
- print('获取选品外观信息--失败',e)
- exit()
- # 获取选品收藏品信息
- def getXpItemset(self):
- print('获取选品收藏品信息')
- try:
- # 创建mysql连接
- conn = mysql.connector.connect(
- host=self.host,
- user=self.user,
- password=self.password,
- database=self.database
- )
- # 创建游标对象
- cursor = conn.cursor()
- # 执行SQL查询
- cursor.execute(f"select colect_code from sys_collect where del_flag = '0' and colect_sta = '0' ")
- # 获取所有记录列表
- results = cursor.fetchall()
- if len(results) == 0:
- print('选品收藏品信息不存在,请检查数据库配置')
- self.xp_itemset_list=[]
- for row in results:
- self.xp_itemset_list.append(row[0])
- # 关闭游标和连接
- cursor.close()
- conn.close()
- except Exception as e:
- print('获取选品收藏品信息--失败',e)
- exit()
- # 获取选品账号信息
- def getXpzh(self):
- print('获取选品账号信息')
- try:
- # 创建mysql连接
- conn = mysql.connector.connect(
- host=self.host,
- user=self.user,
- password=self.password,
- database=self.database
- )
- # 创建游标对象
- cursor = conn.cursor()
- # 执行SQL查询
- cursor.execute(f"SELECT id,phone,email,email_dh,cookie FROM sc_xpzh where phone = '{self.args.xp_phone}' and is_del='0' ")
- # 获取所有记录列表
- results = cursor.fetchall()
- if len(results) == 0:
- print('选品账号信息不存在,请检查手机号码是否正确')
- exit()
- for row in results:
- self.xpzh_email = row[2]
- self.xpzh_email_dh = row[3]
- self.xpzh_cookie = row[4]
- # 关闭游标和连接
- cursor.close()
- conn.close()
- print(f"选品账号手机号码: {self.args.xp_phone}")
- print(f"选品账号email:{self.xpzh_email}")
- print(f"选品账号cookie:{self.xpzh_cookie}")
- print(f"选品账号email:{self.xpzh_email}")
- except Exception as e:
- print('获取选品账号信息--失败',e)
- exit()
- # 获取检索BUFF物品的API接口入参
- def getSearchGoodParam(self):
- print('获取检索BUFF物品API接口入参')
- # 过滤掉空的列表
- non_empty_lists = {
- 'category': self.xp_category_list,
- 'rarity': self.xp_rarity_list,
- 'quality': self.xp_quality_list,
- 'exterior': self.xp_exterior_list,
- 'itemset': self.xp_itemset_list
- }
- # 只保留非空的列表
- filtered_lists = {k: v for k, v in non_empty_lists.items() if v}
- # 如果所有列表都为空,返回空列表
- if not filtered_lists:
- return []
- # 生成所有可能的组合
- # 使用itertools.product来生成所有可能的组合
- from itertools import product
- # 获取所有非空列表的值
- values = list(filtered_lists.values())
- # 获取所有非空列表的键
- keys = list(filtered_lists.keys())
- for combination in product(*values):
- combination_dict = {keys[i]: combination[i] for i in range(len(keys))}
- self.search_good_param_list.append(combination_dict)
- for i in range(len(self.search_good_param_list)):
- self.search_good_param_list[i]['category_group'] = self.search_good_param_list[i]['category']
- # 生成检索BUFF物品的API接口最终入参
- def generate_combinations(self):
- #当self.search_good_param_list为空,加入一个空对象
- if len(self.search_good_param_list) == 0:
- self.search_good_param_list.append({})
- #遍历search_good_param_list数组,每个数组中增加search_good_param_init的值
- for i in range(len(self.search_good_param_list)):
- self.search_good_param_list[i].update(self.search_good_param_init)
- #xptz_status为2时候,将search_good_param_list数组中的每个数组的xptz_page_num和xptz_page_size
- if self.args.xptz_status == 2:
- for i in range(len(self.search_good_param_list)):
- self.search_good_param_list[i]['page_num'] = self.args.xptz_page_num
- self.search_good_param_list[i]['page_size'] = self.args.xptz_page_size
- elif self.args.xptz_status == 1:
- for i in range(len(self.search_good_param_list)):
- self.search_good_param_list[i]['page_num'] = self.args.xptz_page_num
- self.search_good_param_list[i]['page_size'] = self.args.xptz_page_size
- #选品最低价不为空,则将search_good_param_list数组中的每个数组的xptz_min_price的值设置为命令行参数--xptz_min_price的值
- if self.args.xp_min_price != None:
- for i in range(len(self.search_good_param_list)):
- self.search_good_param_list[i]['min_price'] = self.args.xp_min_price
- #选品最高价不为空,则将search_good_param_list数组中的每个数组的xptz_max_price的值设置为命令行参数--xptz_max_price的值
- if self.args.xp_max_price != None:
- for i in range(len(self.search_good_param_list)):
- self.search_good_param_list[i]['max_price'] = self.args.xp_max_price
- #选品排序值不为空,则将search_good_param_list数组中的每个数组的xptz_sort_type的值设置为命令行参数--xptz_sort_type的值
- if self.args.xp_sort != None:
- for i in range(len(self.search_good_param_list)):
- self.search_good_param_list[i]['sort_by'] = self.args.xp_sort
- # 选品
- def SearchGoods(self):
- print('选品开始')
- #simpleSearchGoods函数执行runcount次数,自动停止,两次之间暂停runtime秒
- for i in range(self.args.runcount):
- self.simpleSearchGoods(i)
- time.sleep(self.args.runtime)
- print('选品结束')
- # 单次选品
- def simpleSearchGoods(self,i):
- # 如果搜寻的BUFF商品已完成,则停止脚本
- if self.searchedGoodsNum >= self.args.xptz_success_num:
- print('搜寻的BUFF商品已完成,停止脚本')
- exit()
- # print(f'选品程序第{i}次执行开始')
- # print(self.search_good_param_list)
- # 遍历search_good_param_list
- for param in self.search_good_param_list:
- # print('选品入参:',param)
- # 获取BUFF商品信息
- gooditems = self.callMarketGoods(param)
- # print(gooditems)
- # 判断是否满足条件
- # 此处调整到单独的脚本xpjb-02.py处理
- # print(f'选品程序第{i}次执行结束')
- # 请求BUFF物品的API接口
- def callMarketGoods(self,param):
- # print('获取商品信息')
- #Cookie赋值
- self.my_headers.update({
- 'Cookie': self.xpzh_cookie
- })
- datalist = []
- try:
- res = req.get(url=self.goodsurl, headers=self.my_headers, params=param)
- # if res.json()['code'] != 'OK' :
- print('选品接口请求返回报文:', res.text.strip())
- # return
- data = res.json()['data']
- datalist.extend(data['items'])
- total_page_num= data['total_page']
- # datalist 入数据库
- self.insertGoods(datalist)
- time.sleep(self.args.timeinterval)
- if total_page_num >= param['page_num']:
- total_page_num = param['page_num']
- # print('商品页数'+str(total_page_num))
- if int(total_page_num) > 1:
- for i in range(1, total_page_num):
- time.sleep(self.args.timeinterval)
- param.update({
- 'page_num': i
- })
- try:
- datalist=[]
- res = req.get(url=self.goodsurl, headers=self.my_headers, params=param)
- # if res.json()['code'] != 'OK' :
- print('选品接口请求返回报文:', res.text.strip())
- # continue
- data = res.json()['data']
- datalist.extend(data['items'])
- # datalist 入数据库
- self.insertGoods(datalist)
- except Exception as e:
- print('选品接口请求--失败',e)
- except Exception as e:
- print('选品接口请求--失败',e)
- # print('数据获取成功') # 打印数据列表
- return
- def insertGoods(self,datalist):
- # print('buff商品数据入库')
- try:
- # 创建mysql连接
- conn = mysql.connector.connect(
- host=self.host,
- user=self.user,
- password=self.password,
- database=self.database
- )
- cursor = conn.cursor()
- #遍历datalist
- for item in datalist:
- self.searchedGoodsNum += 1 # 搜索商品数量加1 为了跟入参xptz_success_num要求比对
- print(f"buff商品 id:{item['id']} 已入库")
- query = "INSERT INTO sys_buff_goods (goods_info, deal_flag,create_time) VALUES (%s, %s,now())"
- data = (json.dumps(item), '0')
- cursor.execute(query, data)
- conn.commit()
- except Exception as e:
- print('datalist入库--失败',e)
- finally:
- if conn.is_connected():
- cursor.close()
- conn.close()
- if __name__ == '__main__':
- print('开启选品脚本')
- xp = xpjb()
- # 处理命令行参数
- xp.dealArgc()
- # 获取数据库中BUFF品类配置
- xp.getXpCategory()
- # 获取数据库中BUFF品质配置
- xp.getXpRarity()
- # 获取数据库中BUFF类别配置
- xp.getXpQuality()
- # 获取数据库中BUFF外观配置
- xp.getXpExterior()
- # 获取数据库中BUFF收藏品信息
- xp.getXpItemset()
- # 根据数据库中配置信息,组合商品选取API的入参列表
- xp.getSearchGoodParam()
- # 生成最终选品API的入参列表
- xp.generate_combinations()
- # 获取选品账号信息,根据脚本的入参xp_phone检索
- xp.getXpzh()
- # 选品
- xp.SearchGoods()
|