├── Evaluation.py ├── README.md ├── 京东试用批量全弃用.py └── 自动评价-电脑端.py /Evaluation.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | ''' 4 | 项目名称: JD-Script / jd_Evaluation 5 | Author: qiu_lzsnmb 6 | 功能:全自动完成评价+晒单,提高京享值,满足强迫症 7 | cron: 0 6 */3 * * 8 | new Env('京东全自动评价'); 9 | ''' 10 | 11 | ################【参数】###################### 12 | # [填写您要批量评价的范围] ENV设置: export Ev_Scope='1,2,4-5' 13 | # 目前只支持逗号(,)和减号(-),默认只评价前3个(1-3) 14 | import json.decoder 15 | 16 | Ev_Scope = '' 17 | 18 | # 晒单图片更换 ,默认两张裂图随机 ENV设置: export Ev_img='//img30.360buyimg.com/shaidan/······.jpg' 19 | Ev_img = '' 20 | 21 | # 评价星级,评论是好评,星级默认4-5随机。只支持逗号 ENV设置: export Ev_xing='4,5' 22 | Ev_xing = '4,5' 23 | ############################################### 24 | 25 | import os 26 | import random 27 | import re 28 | import sys 29 | import time 30 | from urllib.parse import unquote 31 | 32 | # noinspection PyUnresolvedReferences 33 | from sendNotify import send 34 | 35 | try: 36 | import requests 37 | except Exception as e: 38 | print(e, "\n缺少requests 模块,请执行命令安装:pip3 install requests") 39 | exit(3) 40 | 41 | try: 42 | import jieba.analyse 43 | 44 | jieba.setLogLevel(jieba.logging.INFO) 45 | except Exception as e: 46 | print(e, "\n缺少jieba 模块,请执行命令安装:pip3 install jieba") 47 | exit(3) 48 | 49 | pwd = os.path.dirname(os.path.abspath(__file__)) + os.sep 50 | 51 | 52 | def printf(text): 53 | print(text) 54 | sys.stdout.flush() 55 | 56 | 57 | def getEnvs(label): 58 | try: 59 | if label == 'True' or label == 'yes' or label == 'true' or label == 'Yes': 60 | return True 61 | elif label == 'False' or label == 'no' or label == 'false' or label == 'No': 62 | return False 63 | except Exception as e: 64 | pass 65 | try: 66 | if '.' in label: 67 | return float(label) 68 | elif '&' in label: 69 | return label.split('&') 70 | elif '@' in label: 71 | return label.split('@') 72 | else: 73 | return int(label) 74 | except: 75 | return label 76 | 77 | 78 | if "Ev_Scope" in os.environ: 79 | if len(os.environ["Ev_Scope"]) > 1: 80 | Ev_Scope = os.environ["Ev_Scope"] 81 | printf(f"已获取并使用Env环境 Ev_Scope:{Ev_Scope}") 82 | 83 | if "Ev_img" in os.environ: 84 | if len(os.environ["Ev_img"]) > 1: 85 | blueCoin_Cc = getEnvs(os.environ["Ev_img"]) 86 | printf(f"已获取并使用Env环境 Ev_img:{Ev_img}") 87 | 88 | if "Ev_xing" in os.environ: 89 | if len(os.environ["Ev_xing"]) > 1: 90 | blueCoin_Cc = getEnvs(os.environ["Ev_xing"]) 91 | printf(f"已获取并使用Env环境 Ev_xing:{Ev_xing}") 92 | 93 | try: 94 | xing = [] 95 | for i in Ev_xing.split(','): 96 | xing.append(i) 97 | except ValueError: 98 | print('星级参数设置错误') 99 | exit(3) 100 | 101 | Scope = [] 102 | 103 | # 范围配置!! 104 | try: 105 | if Ev_Scope == '': 106 | Scope = [1, 2, 3] 107 | else: 108 | for Sco in Ev_Scope.split(','): 109 | if '-' in Sco: 110 | b = Sco.split('-') 111 | for x in range(int(b[0]), int(b[1]) + 1): 112 | Scope.append(x) 113 | else: 114 | Scope.append(int(Sco)) 115 | except ValueError: 116 | print('当前Ev_Scope出错,程序终止!') 117 | exit(3) 118 | 119 | 120 | class getJDCookie(object): 121 | # 适配各种平台环境ck 122 | 123 | def getckfile(self): 124 | global v4f 125 | curf = pwd + 'JDCookies.txt' 126 | v4f = '/jd/config/config.sh' 127 | ql_new = '/ql/config/env.sh' 128 | ql_old = '/ql/config/cookie.sh' 129 | if os.path.exists(curf): 130 | with open(curf, "r", encoding="utf-8") as f: 131 | cks = f.read() 132 | f.close() 133 | r = re.compile(r"pt_key=.*?pt_pin=.*?;", re.M | re.S | re.I) 134 | cks = r.findall(cks) 135 | if len(cks) > 0: 136 | return curf 137 | else: 138 | pass 139 | if os.path.exists(ql_new): 140 | printf("当前环境青龙面板新版") 141 | return ql_new 142 | elif os.path.exists(ql_old): 143 | printf("当前环境青龙面板旧版") 144 | return ql_old 145 | elif os.path.exists(v4f): 146 | printf("当前环境V4") 147 | return v4f 148 | return curf 149 | 150 | # 获取cookie 151 | def getCookie(self): 152 | global cookies 153 | ckfile = self.getckfile() 154 | try: 155 | if os.path.exists(ckfile): 156 | with open(ckfile, "r", encoding="utf-8") as f: 157 | cks = f.read() 158 | f.close() 159 | if 'pt_key=' in cks and 'pt_pin=' in cks: 160 | r = re.compile(r"pt_key=.*?pt_pin=.*?;", re.M | re.S | re.I) 161 | cks = r.findall(cks) 162 | if len(cks) > 0: 163 | if 'JDCookies.txt' in ckfile: 164 | printf("当前获取使用 JDCookies.txt 的cookie") 165 | cookies = '' 166 | for i in cks: 167 | if 'pt_key=xxxx' in i: 168 | pass 169 | else: 170 | cookies += i 171 | return 172 | else: 173 | with open(pwd + 'JDCookies.txt', "w", encoding="utf-8") as f: 174 | cks = "#多账号换行,以下示例:(通过正则获取此文件的ck,理论上可以自定义名字标记ck,也可以随意摆放ck)\n账号1【Curtinlv】cookie1;\n账号2【TopStyle】cookie2;" 175 | f.write(cks) 176 | f.close() 177 | if "JD_COOKIE" in os.environ: 178 | if len(os.environ["JD_COOKIE"]) > 10: 179 | cookies = os.environ["JD_COOKIE"] 180 | printf("已获取并使用Env环境 Cookie") 181 | except Exception as e: 182 | printf(f"【getCookie Error】{e}") 183 | 184 | # 检测cookie格式是否正确 185 | 186 | def getUserInfo(self, ck, pinName, userNum): 187 | url = 'https://me-api.jd.com/user_new/info/GetJDUserInfoUnion?orgFlag=JD_PinGou_New&callSource=mainorder&channel=4&isHomewhite=0&sceneval=2&sceneval=2&callback=' 188 | headers = { 189 | 'Cookie': ck, 190 | 'Accept': '*/*', 191 | 'Connection': 'close', 192 | 'Referer': 'https://home.m.jd.com/myJd/home.action', 193 | 'Accept-Encoding': 'gzip, deflate, br', 194 | 'Host': 'me-api.jd.com', 195 | 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Mobile/15E148 Safari/604.1', 196 | 'Accept-Language': 'zh-cn' 197 | } 198 | try: 199 | if sys.platform == 'ios': 200 | resp = requests.get(url=url, verify=False, headers=headers, timeout=60).json() 201 | else: 202 | resp = requests.get(url=url, headers=headers, timeout=60).json() 203 | if resp['retcode'] == "0": 204 | nickname = resp['data']['userInfo']['baseInfo']['nickname'] 205 | return ck, nickname 206 | else: 207 | context = f"账号{userNum}【{pinName}】Cookie 已失效!请重新获取。" 208 | printf(context) 209 | return ck, False 210 | except Exception: 211 | context = f"账号{userNum}【{pinName}】Cookie 已失效!请重新获取。" 212 | printf(context) 213 | return ck, False 214 | 215 | def iscookie(self): 216 | """ 217 | :return: cookiesList,userNameList,pinNameList 218 | """ 219 | cookiesList = [] 220 | userNameList = [] 221 | pinNameList = [] 222 | if 'pt_key=' in cookies and 'pt_pin=' in cookies: 223 | r = re.compile(r"pt_key=.*?pt_pin=.*?;", re.M | re.S | re.I) 224 | result = r.findall(cookies) 225 | if len(result) >= 1: 226 | printf("您已配置{}个账号".format(len(result))) 227 | u = 1 228 | for i in result: 229 | r = re.compile(r"pt_pin=(.*?);") 230 | pinName = r.findall(i) 231 | pinName = unquote(pinName[0]) 232 | # 获取账号名 233 | ck, nickname = self.getUserInfo(i, pinName, u) 234 | if nickname: 235 | cookiesList.append(ck) 236 | userNameList.append(nickname) 237 | pinNameList.append(pinName) 238 | else: 239 | u += 1 240 | continue 241 | u += 1 242 | if len(cookiesList) > 0 and len(userNameList) > 0: 243 | return cookiesList, userNameList, pinNameList 244 | else: 245 | printf("没有可用Cookie,已退出") 246 | exit(3) 247 | else: 248 | printf("cookie 格式错误!...本次操作已退出") 249 | exit(4) 250 | else: 251 | printf("cookie 格式错误!...本次操作已退出") 252 | exit(4) 253 | 254 | 255 | getCk = getJDCookie() 256 | getCk.getCookie() 257 | # 获取v4环境 特殊处理 258 | if os.path.exists(v4f): 259 | try: 260 | with open(v4f, 'r', encoding='utf-8') as f: 261 | curenv = locals() 262 | for i in f.readlines(): 263 | r = re.compile(r'^export\s(.*?)=[\'\"]?([\w\.\-@#!&=_,\[\]\{\}\(\)]{1,})+[\'\"]{0,1}$', re.M | re.S | re.I) 264 | r = r.findall(i) 265 | if len(r) > 0: 266 | for i in r: 267 | if i[0] != 'JD_COOKIE': 268 | curenv[i[0]] = getEnvs(i[1]) 269 | except: 270 | pass 271 | 272 | if "qjd_zlzh" in os.environ: 273 | if len(os.environ["qjd_zlzh"]) > 1: 274 | qjd_zlzh = os.environ["qjd_zlzh"] 275 | qjd_zlzh = qjd_zlzh.replace('[', '').replace(']', '').replace('\'', '').replace(' ', '').split(',') 276 | # printf("已获取并使用Env环境 qjd_zlzh:", qjd_zlzh) 277 | 278 | 279 | # 评价生成 280 | def generation(pname, _class=0, _type=1): 281 | # 0是追评 1是评价 282 | # class 0是评价 1是提取id 283 | try: 284 | name = jieba.analyse.textrank(pname, topK=5, allowPOS='n')[0] 285 | except: 286 | name = "宝贝" 287 | if _class == 1: 288 | return name 289 | else: 290 | datas = { 291 | 1: { 292 | "开始": [ 293 | "考虑买这个$之前我是有担心过的,因为我不知道$的质量和品质怎么样,但是看了评论后我就放心了。", 294 | "买这个$之前我是有看过好几家店,最后看到这家店的评价不错就决定在这家店买 ", 295 | "看了好几家店,也对比了好几家店,最后发现还是这一家的$评价最好。", 296 | "看来看去最后还是选择了这家。", 297 | "之前在这家店也买过其他东西,感觉不错,这次又来啦。", 298 | "这家的$的真是太好用了,用了第一次就还想再用一次。" 299 | ], 300 | "中间": [ 301 | "收到货后我非常的开心,因为$的质量和品质真的非常的好!", 302 | "拆开包装后惊艳到我了,这就是我想要的$!", 303 | "快递超快!包装的很好!!很喜欢!!!", 304 | "包装的很精美!$的质量和品质非常不错!", 305 | "收到快递后迫不及待的拆了包装。$我真的是非常喜欢", 306 | "真是一次难忘的购物,这辈子没见过这么好用的东西!!" 307 | ], 308 | "结束": [ 309 | "经过了这次愉快的购物,我决定如果下次我还要买$的话,我一定会再来这家店买的。", 310 | "不错不错!", 311 | "我会推荐想买$的朋友也来这家店里买", 312 | "真是一次愉快的购物!", 313 | "大大的好评!以后买$再来你们店!( ̄▽ ̄)", 314 | "大家可以买来试一试,真的是太爽了,一晚上都沉浸在爽之中" 315 | ] 316 | }, 317 | 0: { 318 | "开始": [ 319 | "用了这么久的 $ ,东西是真的好用,真的难忘上一次购买时使用的激动,", 320 | "使用了几天 $ ", 321 | "这是我买到的最好用的$ ", 322 | "我草,是真的好用啊,几天的体验下来,真是怀恋当初购买时下单的那一刻的激动!!!!!!!!!", 323 | "我草,用了几天下来,$ 变得好大好大,这精致的外观,这细腻的皮肤,摸上去,真是令人激动!", 324 | "$ 这小家伙,真是太令人愉悦了,用了都说好好好好!", 325 | "不用睡不着觉,这家店的 $ 真是太好用了。", 326 | "真是牛逼啊,一天不用难受一天,用了一天难受一年!" 327 | ], 328 | "中间": [ 329 | "东西还行,", 330 | "确实是好东西,推荐大家购买,", 331 | "$ 的质量真的非常不错!", 332 | "$ 真是太好用了,真是个宝贝,难忘的宝贝!!", 333 | "$ 短短几天的体验,令人一生难忘", 334 | "$ 用了这么久了,它长的真是太可爱了", 335 | "这可真是个小宝贝!", 336 | "五星好评,安排上,太好用拉!!!" 337 | ], 338 | "结束": [ 339 | "推荐大家来尝试", 340 | "这家店给我对于$能做成这样刷新了世界观!", 341 | "真是一次愉快的购物!", 342 | "以后买$还来这家店,就没见过这么好用的东西!", 343 | "下次还来这家店买 $ ,就没见过这么牛逼的东西", 344 | "东西很好,孩子很喜欢", 345 | "现在睡觉都抱着 $ 睡觉,真是太好用了", 346 | "令人难玩的一次购物" 347 | ] 348 | } 349 | } 350 | if _type == 1: 351 | # return 5, '东西很好,孩子很喜欢,每天晚上不抱着碎觉,就完全睡不着。买的时候看见评论里都说好就买了,看到发货的时候挺激动的,到了之后,满怀期待一激动得从快递员那里拿回了寝室,试一下,结果挺不错啊!而且客服小姐姐也特别的好,很有礼貌,客服小姐姐也是秒回我的疑问呢,嘻嘻,下次还会回购哒。' 352 | comments = datas[_type] 353 | return ( 354 | random.choice(comments["开始"]) + random.choice(comments["中间"]) + random.choice(comments["结束"])).replace("$", name) 355 | elif _type == 0: 356 | comments = datas[_type] 357 | return ( 358 | random.choice(comments["开始"]) + random.choice(comments["中间"]) + random.choice(comments["结束"])).replace("$", name) 359 | 360 | 361 | def start(): 362 | Cent = {} 363 | 364 | def op(headers, _type=True): 365 | Ci = [] 366 | if not _type: 367 | url = 'https://wq.jd.com/bases/orderlist/list?order_type=6&start_page=1&page_size=10' 368 | he = headers 369 | he['referer'] = 'https://wqs.jd.com/order/orderlist_merge.shtml?jxsid=16355625882984298965&orderType=all&ptag=7155.1.11' 370 | # try: 371 | if True: 372 | page = 1 373 | judgmentAndEvaluation = 0 # 判断是否评价完成 374 | OUT = True 375 | while OUT: 376 | req = requests.get(f'https://wq.jd.com/bases/orderlist/list?order_type=6&start_page={page}&last_page=0&page_size=10', headers=he) 377 | data = req.json() 378 | for i, da in enumerate(data['orderList']): 379 | oid = da['orderId'] 380 | if len(da['productList']) == 1: # 单订单 381 | pid = da['productList'][0]['skuId'] 382 | name = da['productList'][0]['title'] 383 | cname = None 384 | for j in da['buttonList']: 385 | if j['id'] == 'toComment': 386 | cname = j['name'] # 评价按钮名字 387 | if cname is None: 388 | # printf("没获得到按钮数据,跳过这个商品!") 389 | continue 390 | elif cname == '查看评价': 391 | judgmentAndEvaluation += 1 392 | if judgmentAndEvaluation == 20: 393 | OUT = False 394 | continue 395 | else: 396 | judgmentAndEvaluation = 0 397 | Ci.append({'name': name, 'oid': oid, 'pid': pid, 'cname': cname, 'multi': False}) 398 | else: 399 | # 针对多订单的处理 400 | odd_url = 'https://api.m.jd.com/api?body={"orderId":"%s"}&appid=jd-cphdeveloper-m&functionId=getEvalPage' % oid 401 | odd_req = requests.get(odd_url, headers=he) 402 | odd_data = odd_req.json() 403 | for odd_da in odd_data['data']['jingdong_club_voucherbyorderid_get_response']['userCommentVoList']: 404 | pid = odd_da['productId'] 405 | name = odd_da['productSolrInfo']['fullName'] 406 | after = odd_da['afterDiscussionStatus'] 407 | append = odd_da['append'] 408 | cname = "评价晒单" if after == 0 else "追加评价" if append == 1 else "查看评价" 409 | if cname == "查看评价": 410 | continue 411 | Ci.append({'name': name, 'oid': oid, 'pid': pid, 'cname': cname, 'multi': True}) 412 | # break 413 | 414 | page += 1 415 | # exit() 416 | # except: 417 | # printf('获取评价出错,可能ck失效') 418 | # exit() 419 | return Ci 420 | 421 | # 评价和服务评价 422 | def ordinary(headers, ce): 423 | """ 424 | 425 | :param headers: 验证头 426 | :param ce: 用户信息 427 | :return: 428 | """ 429 | url = "https://wq.jd.com/eval/SendEval?g_login_type=0&g_ty=ajax" 430 | for i, da in enumerate(op(headers)): 431 | he = headers 432 | 433 | def pjsj(): 434 | data = { 435 | 'productId': da['pid'], 436 | 'orderId': da['oid'], 437 | 'score': int(random.choice(xing)), 438 | 'content': generation(da['name']), 439 | 'commentTagStr': 1, 440 | 'userclient': 29, 441 | 'scence': 101100000 442 | } 443 | req = requests.post(url, headers=he, data=data) 444 | if req.json()['errMsg'] == 'success': 445 | # printf("\t普通评价成功!!") 446 | Cent[ce]['评价'] += 1 447 | else: 448 | printf("\t普通评价失败了.......") 449 | printf(req.json()) 450 | printf(data) 451 | 452 | def pjfw(): 453 | se_url = f'https://wq.jd.com/eval/SendDSR' 454 | se_data = { 455 | 'userclient': '29', 456 | 'orderId': da["oid"], 457 | 'otype': random.randint(3, 5), 458 | 'DSR1': random.randint(3, 5), 459 | 'DSR2': random.randint(3, 5), 460 | 'DSR3': random.randint(3, 5), 461 | 'DSR4': random.randint(3, 5), 462 | 'g_login_type': '0', 463 | 'g_ty': 'ls' 464 | } 465 | se_req = requests.get(se_url, headers=he, params=se_data) 466 | if se_req.json()['errMsg'] == 'success': 467 | # printf("\t服务评价成功!!") 468 | Cent[ce]['服务评价'] += 1 469 | else: 470 | printf("\t服务评价失败了.......") 471 | printf(se_data) 472 | 473 | def zjpj(): 474 | zj_url = 'https://wq.jd.com/eval/AppendComment?appid=jd-cphdeveloper-m&functionId=appendComment' 475 | zj_data = { 476 | "productId": da['pid'], 477 | "orderId": da['oid'], 478 | "content": generation(da['name'], _type=0), 479 | 'userclient': 29 480 | } 481 | zj_req = requests.post(zj_url, headers=he, data=zj_data) 482 | if zj_req.json()['errMsg'] == 'success': 483 | # printf("\t追加评价成功!!") 484 | Cent[ce]['追加评价'] += 1 485 | else: 486 | printf("\t追加评价失败了.......") 487 | printf(zj_data) 488 | 489 | printf(f'开始评论{i}[当前类型:{da["cname"]}]\t[{da["oid"]}]') 490 | 491 | if da['cname'] == "评价晒单": 492 | pjsj() 493 | pjfw() 494 | elif da['cname'] == '评价服务': 495 | pjfw() 496 | elif da['cname'] == '追加评价': 497 | zjpj() 498 | else: 499 | printf(da['cname']) 500 | # printf('等待5秒-可持续发展!') 501 | time.sleep(5) 502 | 503 | # 晒单 504 | def sunbw(headers, ce): 505 | global Ev_img 506 | url = "https://wq.jd.com/eval/SendEval?g_login_type=0&g_ty=ajax" 507 | for i, da in enumerate(op(headers, _type=False)): 508 | if da['cname'] == "追加评价": 509 | context = generation(da['name'], _type=0) 510 | printf(f'开始晒单{i}\t[{da["oid"]}]') 511 | if da['multi']: 512 | # printf('\t多个商品跳过!') 513 | continue 514 | url = 'https://comment-api.jd.com/comment/appendComment?sceneval=2&g_login_type=1&g_ty=ajax' 515 | if Ev_img == '': 516 | Ev_img = random.sample( 517 | ['//img30.360buyimg.com/shaidan/jfs/t1/139511/17/26249/850/61852a35Ea7906339/f7eb6b9438917f30.jpg', '//img30.360buyimg.com/shaidan/jfs/t1/143995/15/24443/5327/61860ba4Ecba97817/d7faafa606f76b1f.jpg'], 1) 518 | data = { 519 | 'productId': da['pid'], 520 | 'orderId': da['oid'], 521 | 'content': context, 522 | 'userclient': 29, 523 | 'imageJson': Ev_img 524 | } 525 | req = requests.post(url, headers=headers, data=data) 526 | try: 527 | if req.json().get('data').get('result') != {}: 528 | # printf("\t晒单成功!!!") 529 | Cent[ce]['晒单'] += 1 530 | time.sleep(10) 531 | else: 532 | printf("\t晒单失败...") 533 | printf(req.json()) 534 | # printf('等待5秒-可持续发展!') 535 | time.sleep(20) 536 | except (KeyError, json.decoder.JSONDecodeError): 537 | printf(f'当前无数据!返回,可能被风控,返回的数据:{req.json()}') 538 | return 539 | 540 | printf('### 开始批量评价 ###') 541 | global cookiesList, userNameList, pinNameList, ckNum, beanCount, userCount 542 | cookiesList, userNameList, pinNameList = getCk.iscookie() 543 | 544 | for i, ck, user, pin in zip(range(1, len(cookiesList) + 1), cookiesList, userNameList, pinNameList): 545 | if i not in Scope: 546 | continue 547 | printf(f"\n\n** 开始[账号{i}]-{user} **") 548 | headers = { 549 | 'cookie': ck, 550 | 'user-agent': 'jdltapp;android;1.0.0;9;860105045422157-bce2658d9db5;network/wifi;model/JKM-AL00a;addressid/0;aid/5d84f5872ec4e5c8;oaid/51fe75e7-7e5d-aefc-fbed-ffffdf7f6bd2;osVer/28;appBuild/694;psn/860105045422157-bce2658d9db5|3;psq/26;uid/860105045422157-bce2658d9db5;adk/;ads/;pap/JA2020_3112531|1.0.0|ANDROID', 551 | } 552 | Cent[f'账号{i}[{user}]'] = {'评价': 0, '晒单': 0, '服务评价': 0, '追加评价': 0} 553 | printf('开始评价与服务评价!') 554 | ordinary(headers, f'账号{i}[{user}]') 555 | printf('评价与服务完成!!\n') 556 | 557 | printf('开始晒单!') 558 | sunbw(headers, f'账号{i}[{user}]') 559 | printf('晒单完成!!。等待10秒开始下一个账号\n') 560 | time.sleep(10) 561 | 562 | msg = '' 563 | for i in Cent: 564 | msg += f'{i}\n{Cent[i]}\n\n' 565 | send('京东全自动评价', msg) 566 | # print('京东全自动评价', msg) 567 | 568 | 569 | if __name__ == '__main__': 570 | start() 571 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 自动评价 2 | 3 | ### PC版于2022年1月1日11:20:00更新 4 | 5 | ### 手机版2022年1月2日10:50:00修复 6 | 7 | ------ 8 | 9 | ###### 手机版和PC版的区别是ck,PC版用的是电脑网页端的ck,评价全面,但不支持青龙 10 | 11 | ###### 手机版支持青龙,但不保证能全部完成评价 12 | 13 | > 手机版是采集我的订单中已完成的,一直采集,直到有20个连续的查看评价(已完成)才会停止 14 | > 15 | > **优点:更全面** 16 | > **缺点:少于20个已完成的评价,导致死循环报错**(解决,多买点东西) 17 | > 不会晒单图片下次我买很多东西的时候在写。可先用电脑版来应急 18 | 19 | **可以试试电脑版的,网页抓个ck。丢进去,运行1-2次,保证全部追评和晒单都完成!!!** 20 | 21 | ------ 22 | 23 | ### 2022/1/2 --10:49 24 | 25 | **手机版** 修复了大部分人晒单报错,原因晒单忘记加延时了。。。 26 | 27 | ------ 28 | 29 | ### 2020/1/1 -- 11:20 30 | 31 | **手机版** 增加了追加评价,完善优化,评价更全面!!! 32 | 33 | **PC版** 优化速度,修复小bug(还有可能报错,多运行几次就好。如果还不行,在发Issues) 34 | 35 | -------------------------------------------------------------------------------- /京东试用批量全弃用.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author:qiu_lzsnmb 5 | @file:京东试用批量全弃用.py 6 | @time:2021/11/25 7 | """ 8 | 9 | import requests 10 | from lxml import etree 11 | 12 | # 网页ck 13 | ck = '' 14 | 15 | headers = { 16 | 'cookie': ck, 17 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36', 18 | 'Referer': 'https://try.jd.com/user/myTrial?page=1&selected=2' 19 | } 20 | 21 | # for i in range(1, int(input("请输入要弃用到第几页: ")) + 1): 22 | for i in range(1, 4): 23 | url = f'https://try.jd.com/user/myTrial?page={i}&selected=2' 24 | req = requests.get(url, headers=headers) 25 | req_et = etree.HTML(req.text) 26 | evaluate_data = req_et.xpath('//*[@id="tab"]/div[3]/div/div/@activity_id') 27 | print(evaluate_data) 28 | for evaluate in evaluate_data: 29 | Zurl = f'https://try.jd.com/user/giveUpTry?activityId={evaluate}&reason=1%E3%80%81%20%E6%88%91%E7%8E%B0%E5%9C%A8%E4%B8%8D%E6%83%B3/%E6%97%A0%E6%B3%95%E8%AF%95%E7%94%A8%E8%BF%99%E6%AC%BE%E4%BA%A7%E5%93%81%EF%BC%9B' 30 | zreq = requests.get(Zurl, headers=headers) 31 | print(zreq.text) 32 | -------------------------------------------------------------------------------- /自动评价-电脑端.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2021/10/23 17:39 3 | import random 4 | import time 5 | import jieba.analyse 6 | import requests 7 | from lxml import etree 8 | 9 | jieba.setLogLevel(jieba.logging.INFO) 10 | """ 11 | ck填到下面就好,只支持网页版的Ck 12 | 以下为最短格式 13 | """ 14 | # ck = 'thor=; pin=;' 15 | ck = input("ck: ") 16 | headers = { 17 | 'cookie': ck, 18 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36', 19 | } 20 | 21 | 22 | # 评价生成 23 | def generation(pname, _class=0, _type=1): 24 | # 0是追评 1是评价 25 | # class 0是评价 1是提取id 26 | try: 27 | name = jieba.analyse.textrank(pname, topK=5, allowPOS='n')[0] 28 | except: 29 | name = "宝贝" 30 | if _class == 1: 31 | return name 32 | else: 33 | datas = { 34 | 1: { 35 | "开始": [ 36 | "考虑买这个$之前我是有担心过的,因为我不知道$的质量和品质怎么样,但是看了评论后我就放心了。", 37 | "买这个$之前我是有看过好几家店,最后看到这家店的评价不错就决定在这家店买 ", 38 | "看了好几家店,也对比了好几家店,最后发现还是这一家的$评价最好。", 39 | "看来看去最后还是选择了这家。", 40 | "之前在这家店也买过其他东西,感觉不错,这次又来啦。", 41 | "这家的$的真是太好用了,用了第一次就还想再用一次。" 42 | ], 43 | "中间": [ 44 | "收到货后我非常的开心,因为$的质量和品质真的非常的好!", 45 | "拆开包装后惊艳到我了,这就是我想要的$!", 46 | "快递超快!包装的很好!!很喜欢!!!", 47 | "包装的很精美!$的质量和品质非常不错!", 48 | "收到快递后迫不及待的拆了包装。$我真的是非常喜欢", 49 | "真是一次难忘的购物,这辈子没见过这么好用的东西!!" 50 | ], 51 | "结束": [ 52 | "经过了这次愉快的购物,我决定如果下次我还要买$的话,我一定会再来这家店买的。", 53 | "不错不错!", 54 | "我会推荐想买$的朋友也来这家店里买", 55 | "真是一次愉快的购物!", 56 | "大大的好评!以后买$再来你们店!( ̄▽ ̄)", 57 | "大家可以买来试一试,真的是太爽了,一晚上都沉浸在爽之中" 58 | ] 59 | }, 60 | 0: { 61 | "开始": [ 62 | "用了这么久的 $ ,东西是真的好用,真的难忘上一次购买时使用的激动,", 63 | "使用了几天 $ ", 64 | "这是我买到的最好用的$ ", 65 | "我草,是真的好用啊,几天的体验下来,真是怀恋当初购买时下单的那一刻的激动!!!!!!!!!", 66 | "我草,用了几天下来,$ 变得好大好大,这精致的外观,这细腻的皮肤,摸上去,真是令人激动!", 67 | "$ 这小家伙,真是太令人愉悦了,用了都说好好好好!", 68 | "不用睡不着觉,这家店的 $ 真是太好用了。", 69 | "真是牛逼啊,一天不用难受一天,用了一天难受一年!" 70 | ], 71 | "中间": [ 72 | "东西还行,", 73 | "确实是好东西,推荐大家购买,", 74 | "$ 的质量真的非常不错!", 75 | "$ 真是太好用了,真是个宝贝,难忘的宝贝!!", 76 | "$ 短短几天的体验,令人一生难忘", 77 | "$ 用了这么久了,它长的真是太可爱了", 78 | "这可真是个小宝贝!", 79 | "五星好评,安排上,太好用拉!!!" 80 | ], 81 | "结束": [ 82 | "推荐大家来尝试", 83 | "这家店给我对于$能做成这样刷新了世界观!", 84 | "真是一次愉快的购物!", 85 | "以后买$还来这家店,就没见过这么好用的东西!", 86 | "下次还来这家店买 $ ,就没见过这么牛逼的东西", 87 | "东西很好,孩子很喜欢", 88 | "现在睡觉都抱着 $ 睡觉,真是太好用了", 89 | "令人难玩的一次购物" 90 | ] 91 | } 92 | } 93 | if _type == 1: 94 | # return 5, '东西很好,孩子很喜欢,每天晚上不抱着碎觉,就完全睡不着。买的时候看见评论里都说好就买了,看到发货的时候挺激动的,到了之后,满怀期待一激动得从快递员那里拿回了寝室,试一下,结果挺不错啊!而且客服小姐姐也特别的好,很有礼貌,客服小姐姐也是秒回我的疑问呢,嘻嘻,下次还会回购哒。' 95 | comments = datas[_type] 96 | return random.randint(3, 5), ( 97 | random.choice(comments["开始"]) + random.choice(comments["中间"]) + random.choice(comments["结束"])).replace( 98 | "$", name) 99 | elif _type == 0: 100 | comments = datas[_type] 101 | return ( 102 | random.choice(comments["开始"]) + random.choice(comments["中间"]) + random.choice(comments["结束"])).replace( 103 | "$", name) 104 | 105 | 106 | # 查询全部评价 107 | def all_evaluate(): 108 | N = {} 109 | url = 'https://club.jd.com/myJdcomments/myJdcomment.action?' 110 | req = requests.get(url, headers=headers) 111 | req_et = etree.HTML(req.text) 112 | evaluate_data = req_et.xpath('//*[@id="main"]/div[2]/div[1]/div/ul/li') 113 | # print(evaluate) 114 | for i, ev in enumerate(evaluate_data): 115 | na = ev.xpath('a/text()')[0] 116 | try: 117 | num = ev.xpath('b/text()')[0] 118 | except IndexError: 119 | num = 0 120 | N[na] = int(num) 121 | return N 122 | 123 | 124 | # 普通评价 125 | def ordinary(N): 126 | Order_data = [] 127 | req_et = [] 128 | for i in range((N['待评价订单'] // 20) + 1): 129 | url = f'https://club.jd.com/myJdcomments/myJdcomment.action?sort=0&page={i + 1}' 130 | req = requests.get(url, headers=headers) 131 | req_et.append(etree.HTML(req.text)) 132 | for i in req_et: 133 | Order_data.extend(i.xpath('//*[@id="main"]/div[2]/div[2]/table/tbody')) 134 | if len(Order_data) != N['待评价订单']: 135 | Order_data = [] 136 | for i in req_et: 137 | Order_data.extend(i.xpath('//*[@id="main"]/div[2]/div[2]/table')) 138 | 139 | print(f"当前共有{N['待评价订单']}个评价。") 140 | for i, Order in enumerate(Order_data): 141 | oid = Order.xpath('tr[@class="tr-th"]/td/span[3]/a/text()')[0] 142 | oname_data = Order.xpath('tr[@class="tr-bd"]/td[1]/div[1]/div[2]/div/a/text()') 143 | pid_data = Order.xpath('tr[@class="tr-bd"]/td[1]/div[1]/div[2]/div/a/@href') 144 | for oname, pid in zip(oname_data, pid_data): 145 | pid = pid.replace('//item.jd.com/', '').replace('.html', '') 146 | 147 | print(f"\t{i}.开始评价订单\t{oname}[{oid}]") 148 | url2 = f"https://club.jd.com/myJdcomments/saveProductComment.action" 149 | xing, Str = generation(oname) 150 | print(f'\t\t评价内容,星级{xing}:', Str) 151 | data2 = { 152 | 'orderId': oid, 153 | 'productId': pid, # 商品id 154 | 'score': str(xing), # 商品几星 155 | 'content': bytes(Str, encoding="gbk"), # 评价内容 156 | 'saveStatus': '1', 157 | 'anonymousFlag': '1' 158 | } 159 | pj2 = requests.post(url2, headers=headers, data=data2) 160 | time.sleep(2) 161 | N['待评价订单'] -= 1 162 | return N 163 | 164 | 165 | # 晒单评价 166 | def sunbw(N): 167 | Order_data = [] 168 | for i in range((N['待晒单'] // 20) + 1): 169 | url = f"https://club.jd.com/myJdcomments/myJdcomment.action?sort=1&page={i + 1}" 170 | req = requests.get(url, headers=headers) 171 | req_et = etree.HTML(req.text) 172 | Order_data.extend(req_et.xpath('//*[@id="evalu01"]/div[2]/div[1]/div[@class="comt-plist"]/div[1]')) 173 | print(f"当前共有{N['待晒单']}个需要晒单。") 174 | for i, Order in enumerate(Order_data): 175 | oname = Order.xpath('ul/li[1]/div/div[2]/div[1]/a/text()')[0] 176 | pid = Order.xpath('@pid')[0] 177 | oid = Order.xpath('@oid')[0] 178 | 179 | print(f'\t开始晒单{i},{oname}') 180 | # 获取图片 181 | pname = generation(pname=oname, _class=1) 182 | url1 = f"https://club.jd.com/discussion/getProductPageImageCommentList.action?productId={pid}" 183 | imgdata = requests.get(url1, headers=headers).json() 184 | if imgdata["imgComments"]["imgCommentCount"] == 0: 185 | url1 = "https://club.jd.com/discussion/getProductPageImageCommentList.action?productId=1190881" 186 | imgdata = requests.get(url1, headers=headers).json() 187 | imgurl = imgdata["imgComments"]["imgList"][0]["imageUrl"] 188 | 189 | # 190 | print(f'\t\t图片url={imgurl}') 191 | url2 = "https://club.jd.com/myJdcomments/saveShowOrder.action" # 提交晒单 192 | headers['Referer'] = 'https://club.jd.com/myJdcomments/myJdcomment.action?sort=1' 193 | headers['Origin'] = 'https://club.jd.com' 194 | headers['Content-Type'] = 'application/x-www-form-urlencoded' 195 | data = { 196 | 'orderId': oid, 197 | 'productId': pid, 198 | 'imgs': imgurl, 199 | 'saveStatus': 3 200 | } 201 | req_url2 = requests.post(url2, data={ 202 | 'orderId': oid, 203 | 'productId': pid, 204 | 'imgs': imgurl, 205 | 'saveStatus': 3 206 | }, headers=headers) 207 | # print(f'\t\t\t{req_url2.text}') 208 | print('完成') 209 | time.sleep(5) 210 | N['待晒单'] -= 1 211 | return N 212 | 213 | 214 | # 追评 215 | def review(N): 216 | req_et = [] 217 | Order_data = [] 218 | for i in range((N['待追评'] // 20) + 1): 219 | url = f"https://club.jd.com/myJdcomments/myJdcomment.action?sort=3&page={i + 1}" 220 | req = requests.get(url, headers=headers) 221 | req_et.append(etree.HTML(req.text)) 222 | for i in req_et: 223 | Order_data.extend(i.xpath('//*[@id="main"]/div[2]/div[2]/table/tr[@class="tr-bd"]')) 224 | if len(Order_data) != N['待追评']: 225 | for i in req_et: 226 | Order_data.extend(i.xpath('//*[@id="main"]/div[2]/div[2]/table/tbody/tr[@class="tr-bd"]')) 227 | print(f"当前共有{N['待追评']}个需要追评。") 228 | for i, Order in enumerate(Order_data): 229 | oname = Order.xpath('td[1]/div/div[2]/div/a/text()')[0] 230 | _id = Order.xpath('td[3]/div/a/@href')[0] 231 | # date = Order.xpath('td[2]/div/text()')[0] 232 | print(f'\t开始第{i},{oname}') 233 | url1 = "https://club.jd.com/afterComments/saveAfterCommentAndShowOrder.action" 234 | pid, oid = _id.replace('http://club.jd.com/afterComments/productPublish.action?sku=', "").split('&orderId=') 235 | context = generation(oname, _type=0) 236 | print(f'\t\t追评内容:{context}') 237 | req_url1 = requests.post(url1, headers=headers, data={ 238 | 'orderId': oid, 239 | 'productId': pid, 240 | 'content': bytes(context, encoding="gbk"), 241 | 'anonymousFlag': 1, 242 | 'score': 5 243 | }) 244 | # print(f'\t\t\tr{req_url1.text}') 245 | print('完成') 246 | time.sleep(2) 247 | N['待追评'] -= 1 248 | return N 249 | 250 | 251 | # 服务评价 252 | def Service_rating(N): 253 | Order_data = [] 254 | req_et = [] 255 | for i in range((N['服务评价'] // 20) + 1): 256 | url = f"https://club.jd.com/myJdcomments/myJdcomment.action?sort=4&page={i + 1}" 257 | req = requests.get(url, headers=headers) 258 | req_et.append(etree.HTML(req.text)) 259 | for i in req_et: 260 | Order_data.extend(i.xpath('//*[@id="main"]/div[2]/div[2]/table/tbody/tr[@class="tr-bd"]')) 261 | if len(Order_data) != N['服务评价']: 262 | for i in req_et: 263 | Order_data.extend(i.xpath('//*[@id="main"]/div[2]/div[2]/table/tr[@class="tr-bd"]')) 264 | print(f"当前共有{N['服务评价']}个需要服务评价。") 265 | for i, Order in enumerate(Order_data): 266 | oname = Order.xpath('td[1]/div[1]/div[2]/div/a/text()')[0] 267 | oid = Order.xpath('td[4]/div/a[1]/@oid')[0] 268 | print(f'\t开始第{i},{oname}') 269 | url1 = f'https://club.jd.com/myJdcomments/insertRestSurvey.action?voteid=145&ruleid={oid}' 270 | data1 = { 271 | 'oid': oid, 272 | 'gid': '32', 273 | 'sid': '186194', 274 | 'stid': '0', 275 | 'tags': '', 276 | 'ro591': f'591A{random.randint(3, 5)}', # 商品符合度 277 | 'ro592': f'592A{random.randint(3, 5)}', # 店家服务态度 278 | 'ro593': f'593A{random.randint(3, 5)}', # 快递配送速度 279 | 'ro899': f'899A{random.randint(3, 5)}', # 快递员服务 280 | 'ro900': f'900A{random.randint(3, 5)}' # 快递员服务 281 | } 282 | pj1 = requests.post(url1, headers=headers, data=data1) 283 | print("\t\t", pj1.text) 284 | time.sleep(5) 285 | N['服务评价'] -= 1 286 | return N 287 | 288 | 289 | def No(): 290 | print() 291 | N = all_evaluate() 292 | for i in N: 293 | print(i, N[i], end="----") 294 | print() 295 | return N 296 | 297 | 298 | def main(): 299 | print("开始京东批量评价!") 300 | N = No() 301 | if not N: 302 | print('Ck出现错误,请重新抓取!') 303 | exit() 304 | if N['待评价订单'] != 0: 305 | print("1.开始普通评价") 306 | N = ordinary(N) 307 | N = No() 308 | if N['待晒单'] != 0: 309 | print("2.开始晒单评价") 310 | N = sunbw(N) 311 | N = No() 312 | if N['待追评'] != 0: 313 | print("3.开始批量追评!") 314 | N = review(N) 315 | N = No() 316 | if N['服务评价'] != 0: 317 | print('4.开始服务评价') 318 | try: 319 | N = Service_rating(N) 320 | except: 321 | print("有京东快递评价,懒的修复,报错了,就重新在运行一次..................") 322 | N = No() 323 | print("全部完成啦!") 324 | for i in N: 325 | if N[i] != 0: 326 | print("出现了二次错误,跳过了部分,重新尝试") 327 | main() 328 | 329 | 330 | if __name__ == '__main__': 331 | try: 332 | main() 333 | except RecursionError: 334 | print("多次出现未完成情况,程序自动退出") 335 | --------------------------------------------------------------------------------