diff --git a/jd_try.js b/jd_try_2.0.js similarity index 92% rename from jd_try.js rename to jd_try_2.0.js index 2e588d7..13f76c2 100644 --- a/jd_try.js +++ b/jd_try_2.0.js @@ -1,13 +1,26 @@ /* - * 2022-05-27 修复优化版 By https://github.com/6dylan6/jdpro/ - * 如需运行请自行添加环境变量:JD_TRY,值填 true 即可运行 - * X1a0He留 - * 脚本是否耗时只看args_xh.maxLength的大小 - * 上一作者说了每天最多300个商店,总上限为500个,jd_unsubscribe.js我已更新为批量取关版 - * 请提前取关至少250个商店确保京东试用脚本正常运行 + * 2022-07-20 修复获取试用列表风控问题; + * By https://github.com/6dylan6/jdpro/ + * 基于X1a0He版本修改 * @Address: https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js -cron "44 1-22/8 * * *" jd_try.js, tag:京东试用 +如需运行请自行添加环境变量:JD_TRY="true" 即可运行 +脚本是否耗时只看args_xh.maxLength的大小(申请数量),默认50个,申请100个差不多15分钟 +上一作者说每天申请上限300个(自测,没有申请过上限),关注店铺上限500个 +关注店铺满了就无法继续申请,可用批量取关店铺取消关注 + +部分环境变量说明,详细请参考57行往下: +export JD_TRY="true"是否允许,默认false +export JD_TRY_PASSZC="false" #不过滤种草官类试用,默认true过滤 +export JD_TRY_MAXLENGTH="50" #商品数组的最大长度,默认50个 +export JD_TRY_PRICE="XX"#商品原价格,大于XX才申请,默认20 +export JD_TRY_APPLYINTERVAL="6000" #商品试用之间和获取商品之间的间隔ms +export JD_TRY_APPLYNUMFILTER="10000" #过滤大于设定值的已申请人数 +export JD_TRY_MINSUPPLYNUM="1" #最小提供数量 +export JD_TRY_SENDNUM="10" #每隔多少账号发送一次通知,默认为4 +export JD_TRY_UNIFIED="false" 默认采用不同试用组 + +定时自定义,能用多久随缘了!!! */ const $ = new Env('京东试用') const URL = 'https://api.m.jd.com/client.action' @@ -26,18 +39,19 @@ $.getNum = 0; $.try = true; $.sentNum = 0; $.cookiesArr = [] +//默认的过滤关键词 $.innerKeyWords = [ "幼儿园", "教程", "英语", "辅导", "培训", "孩子", "小学", "成人用品", "套套", "情趣", "自慰", "阳具", "飞机杯", "男士用品", "女士用品", "内衣", "高潮", "避孕", "乳腺", "肛塞", "肛门", - "宝宝", "玩具", "芭比", "娃娃", "男用", + "宝宝", "芭比", "娃娃", "男用", "女用", "神油", "足力健", "老年", "老人", "宠物", "饲料", "丝袜", "黑丝", "磨脚", "脚皮", "除臭", "性感", "内裤", "跳蛋", "安全套", "龟头", "阴道", "阴部", "手机卡", "电话卡", "流量卡", - "玉坠","和田玉","习题","试卷","手机壳","钢化膜" + "习题","试卷", ] //下面很重要,遇到问题请把下面注释看一遍再来问 let args_xh = { @@ -81,12 +95,11 @@ let args_xh = { * */ jdPrice: process.env.JD_TRY_PRICE * 1 || 20, /* - * 获取试用商品类型,默认为1 - * 下面有一个function是可以获取所有tabId的,名为try_tabList + * 下面有一个function是可以获取tabId列表,名为try_tabList * 可设置环境变量:JD_TRY_TABID,用@进行分隔 - * 默认为 1 到 10 + * tabId不定期会变,获取不到商品,自行获取并修改tabId * */ - tabId: process.env.JD_TRY_TABID && process.env.JD_TRY_TABID.split('@').map(Number) || [104, 3, 4, 5, 6, 7, 8, 9, 10], + tabId: process.env.JD_TRY_TABID && process.env.JD_TRY_TABID.split('@').map(Number) || [200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212], /* * 试用商品标题过滤,黑名单,当标题存在关键词时,则不加入试用组 * 当白名单和黑名单共存时,黑名单会自动失效,优先匹配白名单,匹配完白名单后不会再匹配黑名单,望周知 @@ -111,23 +124,23 @@ let args_xh = { * */ minSupplyNum: process.env.JD_TRY_MINSUPPLYNUM * 1 || 1, /* - * 过滤大于设定值的已申请人数,例如下面设置的1000,A商品已经有1001人申请了,则A商品不会进行申请,会被跳过 + * 过滤大于设定值的已申请人数,例如下面设置的10000,A商品已经有10001人申请了,则A商品不会进行申请,会被跳过 * 可设置环境变量:JD_TRY_APPLYNUMFILTER * */ - applyNumFilter: process.env.JD_TRY_APPLYNUMFILTER * 1 || 100000, + applyNumFilter: process.env.JD_TRY_APPLYNUMFILTER * 1 || 10000, /* * 商品试用之间和获取商品之间的间隔, 单位:毫秒(1秒=1000毫秒) * 可设置环境变量:JD_TRY_APPLYINTERVAL - * 默认为3000,也就是3秒 + * 默认为6000-9000随机 * */ - applyInterval: process.env.JD_TRY_APPLYINTERVAL * 1 || 30000, + applyInterval: process.env.JD_TRY_APPLYINTERVAL * 1 || 6000, /* * 商品数组的最大长度,通俗来说就是即将申请的商品队列长度 * 例如设置为20,当第一次获取后获得12件,过滤后剩下5件,将会进行第二次获取,过滤后加上第一次剩余件数 * 例如是18件,将会进行第三次获取,直到过滤完毕后为20件才会停止,不建议设置太大 * 可设置环境变量:JD_TRY_MAXLENGTH * */ - maxLength: process.env.JD_TRY_MAXLENGTH * 1 || 100, + maxLength: process.env.JD_TRY_MAXLENGTH * 1 || 50, /* * 过滤种草官类试用,某些试用商品是专属官专属,考虑到部分账号不是种草官账号 * 例如A商品是种草官专属试用商品,下面设置为true,而你又不是种草官账号,那A商品将不会被添加到待提交试用组 @@ -145,7 +158,7 @@ let args_xh = { * 不打印的缺点:无法清晰知道每个商品为什么会被过滤,哪个商品被添加到了待提交试用组 * 可设置环境变量:JD_TRY_PLOG,默认为true * */ - printLog: process.env.JD_TRY_PLOG === 'true' || true, + printLog: process.env.JD_TRY_PLOG === 'false' || true, /* * 白名单,是否打开,如果下面为true,那么黑名单会自动失效 * 白名单和黑名单无法共存,白名单永远优先于黑名单 @@ -169,7 +182,8 @@ let args_xh = { !(async() => { await $.wait(500) // 如果你要运行京东试用这个脚本,麻烦你把环境变量 JD_TRY 设置为 true - if (1) { + if (process.env.JD_TRY && process.env.JD_TRY === 'true') { + $.log('\n遇到问题请先看脚本内注释;解决不了在联系我https://t.me/dylan_jdpro\n'); await requireConfig() if (!$.cookiesArr[0]) { $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/', { @@ -177,6 +191,7 @@ let args_xh = { }) return } + args_xh.tabId = args_xh.tabId.sort(() => 0.5 - Math.random()) for (let i = 0; i < $.cookiesArr.length; i++) { if ($.cookiesArr[i]) { $.cookie = $.cookiesArr[i]; @@ -184,7 +199,7 @@ let args_xh = { $.index = i + 1; $.isLogin = true; $.nickName = ''; - //await totalBean(); + await totalBean(); console.log(`\n开始【京东账号${$.index}】${$.nickName || $.UserName}\n`); $.except = false; if(args_xh.except.includes($.UserName)){ @@ -204,8 +219,8 @@ let args_xh = { $.nowTabIdIndex = 0; $.nowPage = 1; $.nowItem = 1; - - + $.retrynum = 0 + $.jda='__jda='+_jda('1xxxxxxxx.164xxxxxxxxxxxxxxxxxxx.164xxxxxxx.165xxxxxx.165xxxxxx.1xx') if (!args_xh.unified) { trialActivityIdList = [] trialActivityTitleList = [] @@ -217,8 +232,8 @@ let args_xh = { $.isForbidden = false $.wrong = false size = 1 - while(trialActivityIdList.length < args_xh.maxLength && $.isForbidden === false){ - if(args_xh.unified && trialActivityIdList.length !== 0) break; + + while(trialActivityIdList.length < args_xh.maxLength && $.retrynum < 3){ if($.nowTabIdIndex === args_xh.tabId.length){ console.log(`tabId组已遍历完毕,不在获取商品\n`); break; @@ -226,7 +241,7 @@ let args_xh = { await try_feedsList(args_xh.tabId[$.nowTabIdIndex], $.nowPage) //获取对应tabId的试用页面 } if(trialActivityIdList.length < args_xh.maxLength){ - console.log(`间隔等待中,请等待 3 秒\n`) + console.log(`间隔等待中,请等待3秒 \n`) await $.wait(3000); } } @@ -240,7 +255,7 @@ let args_xh = { } await try_apply(trialActivityTitleList[i], trialActivityIdList[i]) //console.log(`间隔等待中,请等待 ${args_xh.applyInterval} ms\n`) - const waitTime = generateRandomInteger(args_xh.applyInterval, 13000); + const waitTime = generateRandomInteger(args_xh.applyInterval, 9000); console.log(`随机等待${waitTime}ms后继续`); await $.wait(waitTime); } @@ -265,14 +280,14 @@ let args_xh = { } } if($.isNode() && $.except === false){ - if(($.cookiesArr.length - ($.sentNum * args_xh.sendNum)) < args_xh.sendNum){ + if(($.cookiesArr.length - ($.sentNum * args_xh.sendNum)) < args_xh.sendNum && notifyMsg.length != 0) { console.log(`正在进行最后一次发送通知,发送数量:${($.cookiesArr.length - ($.sentNum * args_xh.sendNum))}`) await $.notify.sendNotify(`${$.name}`, `${notifyMsg}`) notifyMsg = ""; } } } else { - console.log(`\n您未设置运行【京东试用】脚本,结束运行!\n`) + console.log(`\n您未设置变量export JD_TRY="true"运行【京东试用】脚本, 结束运行!\n`) } })().catch((e) => { console.error(`❗️ ${$.name} 运行错误!\n${e}`) @@ -280,7 +295,6 @@ let args_xh = { function requireConfig() { return new Promise(resolve => { - console.log('开始获取配置文件\n') $.notify = $.isNode() ? require('./sendNotify') : { sendNotify: async () => { } } //获取 Cookies $.cookiesArr = [] @@ -298,7 +312,7 @@ function requireConfig() { for(let keyWord of $.innerKeyWords) args_xh.titleFilters.push(keyWord) console.log(`共${$.cookiesArr.length}个京东账号\n`) if(args_xh.env){ - console.log('=====环境变量配置如下=====') + console.log('=========环境变量配置如下=========') console.log(`env: ${typeof args_xh.env}, ${args_xh.env}`) console.log(`except: ${typeof args_xh.except}, ${args_xh.except}`) console.log(`totalPages: ${typeof args_xh.totalPages}, ${args_xh.totalPages}`) @@ -315,7 +329,7 @@ function requireConfig() { console.log(`printLog: ${typeof args_xh.printLog}, ${args_xh.printLog}`) console.log(`whiteList: ${typeof args_xh.whiteList}, ${args_xh.whiteList}`) console.log(`whiteListKeywords: ${typeof args_xh.whiteListKeywords}, ${args_xh.whiteListKeywords}`) - console.log('=======================') + console.log('===============================') } resolve() }) @@ -366,15 +380,16 @@ function try_feedsList(tabId, page) { "version": 2, "source": "default", "client": "app", - "previewTime": "" + //"previewTime": "" }); let option = taskurl_xh('newtry', 'try_feedsList', body) $.post(option, (err, resp, data) => { try{ if(err){ - if(JSON.stringify(err) === `\"Response code 403 (Forbidden)\"`){ - $.isForbidden = true - console.log('账号被京东服务器风控,不再请求该帐号') + if(JSON.stringify(err) === `\"Response code 403 (Forbidden)\"`){ + console.log(`请求失败,第 ${$.retrynum+1} 次重试`) + $.retrynum++ + if($.retrynum === 3) {$.isForbidden = true;$.log('多次尝试失败,换个时间再试!')} } else { console.log(JSON.stringify(err)) console.log(`${$.name} API请求失败,请检查网路重试`) @@ -430,19 +445,23 @@ function try_feedsList(tabId, page) { } else { tempKeyword = ``; if (parseFloat(item.jdPrice) <= args_xh.jdPrice) { - args_xh.printLog ? console.log(`商品被过滤,${item.jdPrice} < ${args_xh.jdPrice} \n`) : '' + args_xh.printLog ? console.log(`商品被过滤,商品价格 ${item.jdPrice} < ${args_xh.jdPrice} \n`) : '' } else if (parseFloat(item.supplyNum) < args_xh.minSupplyNum && item.supplyNum !== null) { args_xh.printLog ? console.log(`商品被过滤,提供申请的份数小于预设申请的份数 \n`) : '' } else if (parseFloat(item.applyNum) > args_xh.applyNumFilter && item.applyNum !== null) { - args_xh.printLog ? console.log(`商品被过滤,已申请试用人数大于预设人数 \n`) : '' - } else if (parseFloat(item.jdPrice) < args_xh.jdPrice) { - args_xh.printLog ? console.log(`商品被过滤,商品原价低于预设商品原价 \n`) : '' + args_xh.printLog ? console.log(`商品被过滤,已申请人数大于预设的${args_xh.applyNumFilter}人 \n`) : '' + } else if (item.jdPrice === null) { + args_xh.printLog ? console.log(`商品被过滤,商品无价,不能申请 \n`) : '' + } else if (parseFloat(item.trialPrice) > args_xh.trialPrice) { + args_xh.printLog ? console.log(`商品被过滤,商品试用价大于预设试用价 \n`) : '' } else if (args_xh.titleFilters.some(fileter_word => item.skuTitle.includes(fileter_word) ? tempKeyword = fileter_word : '')) { args_xh.printLog ? console.log(`商品被过滤,含有关键词 ${tempKeyword}\n`) : '' } else { - args_xh.printLog ? console.log(`商品通过,将加入试用组,trialActivityId为${item.trialActivityId}\n`) : '' + args_xh.printLog ? console.log(`商品通过,加入试用组,trialActivityId为${item.trialActivityId}\n`) : '' + if (trialActivityIdList.indexOf(item.trialActivityId) === -1){ trialActivityIdList.push(item.trialActivityId) trialActivityTitleList.push(item.skuTitle) + } } } } else if ($.isPush !== false) { @@ -451,13 +470,14 @@ function try_feedsList(tabId, page) { } } console.log(`当前试用组长度为:${trialActivityIdList.length}`) - args_xh.printLog ? console.log(`${trialActivityIdList}`) : '' + //args_xh.printLog ? console.log(`${trialActivityIdList}`) : '' if (page >= args_xh.totalPages && $.nowTabIdIndex < args_xh.tabId.length) { //这个是因为每一个tab都会有对应的页数,获取完如果还不够的话,就获取下一个tab $.nowTabIdIndex++; $.nowPage = 1; $.nowItem = 1; } + $.retrynum = 0 } else { console.log(`💩 获得试用列表失败: ${data.message}`) } @@ -524,6 +544,7 @@ function try_apply(title, activityId) { } function try_MyTrials(page, selected) { + return new Promise((resolve, reject) => { switch (selected) { case 1: @@ -545,7 +566,7 @@ function try_MyTrials(page, selected) { 'origin': 'https://prodev.m.jd.com', 'User-Agent': 'jdapp;iPhone;10.3.4;;;M/5.0;appBuild/167945;jdSupportDarkMode/1;;;Mozilla/5.0 (iPhone; CPU iPhone OS 15_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1;', 'referer': 'https://prodev.m.jd.com/', - 'cookie': `${$.cookie} __jda=1.0;` + 'cookie': $.cookie+$.jda }, } $.post(options, (err, resp, data) => { @@ -583,10 +604,11 @@ function try_MyTrials(page, selected) { } function taskurl_xh(appid, functionId, body = JSON.stringify({})) { + return { - "url": `${URL}?appid=${appid}&functionId=${functionId}&clientVersion=10.3.4&client=wh5&body=${encodeURIComponent(body)}`, + "url": `${URL}?appid=${appid}&functionId=${functionId}&clientVersion=10.3.4&client=wh5&body=${encodeURIComponent(body)}&h5st=''`, 'headers': { - 'Cookie': `${$.cookie} __jda=1.0;`, + 'Cookie': $.cookie + $.jda, 'user-agent': 'jdapp;iPhone;10.1.2;15.0;ff2caa92a8529e4788a34b3d8d4df66d9573f499;network/wifi;model/iPhone13,4;addressid/2074196292;appBuild/167802;jdSupportDarkMode/1;Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1', 'Referer': 'https://prodev.m.jd.com/', 'origin': 'https://prodev.m.jd.com/', @@ -683,6 +705,14 @@ function jsonParse(str) { } } } + +function _jda(format = 'xxxxxxxxxxxxxxxxxxxx') { + return format.replace(/[xy]/g, function (c) { + var r = Math.random() * 10 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + jdaid = v.toString() + return jdaid; + }); +} const generateRandomInteger = (min, max = 0) => { if (min > max) { let temp = min; @@ -694,6 +724,12 @@ function jsonParse(str) { return min + Math.round(Rand * Range); }; + function getExtract(array) { + const random = (min, max) => Math.floor(Math.random() * (max - min) + min); + let index=random(0, array.length); + return array.splice(index, 1); +} + function Env(name, opts) { class Http { constructor(env) {