├── cookies_taobao.txt ├── libs ├── __init__.py ├── utils.py ├── wx_bot.py └── alimama.py ├── .gitignore ├── .dockerignore ├── requirements.txt ├── 效果图.png ├── cookies.jpeg ├── IEDriverServer.exe ├── main.py ├── tests └── test_itchat.py ├── Dockerfile └── README.md /cookies_taobao.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /libs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | cookies.txt 2 | itchat.pkl 3 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | cookies.txt 2 | itchat.pkl 3 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | itchat 2 | selenium 3 | qrtools 4 | pillow 5 | zbarlight -------------------------------------------------------------------------------- /效果图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xsren/wx_taobao_fanli/HEAD/效果图.png -------------------------------------------------------------------------------- /cookies.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xsren/wx_taobao_fanli/HEAD/cookies.jpeg -------------------------------------------------------------------------------- /IEDriverServer.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xsren/wx_taobao_fanli/HEAD/IEDriverServer.exe -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xsren 4 | @contact: bestrenxs@gmail.com 5 | @site: xsren.me 6 | 7 | @version: 1.0 8 | @license: Apache Licence 9 | @file: main.py 10 | @time: 2017/5/29 上午10:11 11 | 12 | """ 13 | 14 | from libs.wx_bot import WxBot 15 | 16 | 17 | def run(): 18 | wb = WxBot() 19 | wb.run() 20 | 21 | 22 | if __name__ == '__main__': 23 | run() 24 | -------------------------------------------------------------------------------- /tests/test_itchat.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xsren 4 | @contact: bestrenxs@gmail.com 5 | @site: xsren.me 6 | 7 | @version: 1.0 8 | @license: Apache Licence 9 | @file: test_itchat.py 10 | @time: 2017/5/31 下午5:38 11 | 12 | """ 13 | import threading 14 | 15 | import itchat 16 | 17 | 18 | class MyItchat: 19 | @itchat.msg_register(itchat.content.TEXT) 20 | def text_reply(msg): 21 | print msg.text 22 | 23 | def run(self): 24 | itchat.auto_login() 25 | itchat.run() 26 | 27 | 28 | if __name__ == '__main__': 29 | mi = MyItchat() 30 | t = threading.Thread(target=mi.run, args=()) 31 | t.start() 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Pull base image. 2 | FROM ubuntu:16.04 3 | 4 | # Install. 5 | RUN \ 6 | apt-get -y update && \ 7 | apt-get -y upgrade && \ 8 | apt-get install -y build-essential && \ 9 | apt-get install -y software-properties-common 10 | 11 | RUN \ 12 | apt-get install -y gcc libzbar-dev python-pip && \ 13 | rm -rf /var/lib/apt/lists/* && \ 14 | pip install --upgrade pip 15 | 16 | # Set the working directory to /app 17 | WORKDIR /app 18 | 19 | COPY requirements.txt /app 20 | # Install any needed packages specified in requirements.txt 21 | RUN pip install -r requirements.txt 22 | 23 | # Copy the current directory contents into the container at /app 24 | COPY . /app 25 | 26 | ENV LANG C.UTF-8 27 | 28 | # Run main.py when the container launches 29 | CMD ["python", "main.py"] 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wx_taobao_fanli 2 | 微信 淘宝 返利 3 | 4 | --- 5 | 20190321 更新 6 | 7 | 修复了因为淘宝改版带来的修改。 8 | 先在电脑登录阿里旺旺,再运行脚本。脚本会调用ie插件来快捷登录淘宝联盟,并自动保存cookie到cookies_taobao.txt文件中。 9 | 10 | --- 11 | --- 12 | 20180630 更新 13 | 14 | 因为淘宝改版,扫码登录这块暂时不能用了,现在的做法是在网页上登录淘宝联盟,然后把cookie放在cookies_taobao.txt文件中。淘宝联盟地址:[https://pub.alimama.com/](https://pub.alimama.com/)。cookie如下图所示: 15 | ![](cookies.jpeg) 16 | 17 | --- 18 | 19 | --- 20 | 20171030 更新 21 | 22 | 兼容python3 23 | 24 | --- 25 | 26 | 这个一个微信淘宝返利"机器人",登录以后,匹配到淘宝口令会自动生成可以返利的淘宝口令。 27 | 28 | 功能上主要有两部分: 29 | #### 微信 30 | 网上有现成的,非常感谢 [ItChat](https://github.com/littlecodersh/ItChat)。 31 | #### 淘宝 32 | 在网上没搜到,自己抓包实现了。大概的过程是: 33 | ``` 34 | 1、登录阿里妈妈 35 | 2、根据url搜索相关的商品 36 | 3、生成返利的商品口令 37 | ``` 38 | 39 | #### 依赖 40 | ``` 41 | requests 42 | itchat 43 | ``` 44 | 45 | #### 使用 46 | #####docker运行 47 | 项目根目录下执行 48 | ``` 49 | # 编译镜像 50 | docker build -t xsren/wx_tb_fanli . 51 | # 运行容器 52 | docker run -ti xsren/wx_tb_fanli 53 | ``` 54 | 也可以直接拉取我的镜像 55 | ``` 56 | docker pull xsren/wx_tb_fanli 57 | ``` 58 | #####命令行运行 59 | ``` 60 | python main.py 61 | ``` 62 | 第一次运行会扫两次码,第一个码是淘宝的码,用于登录淘宝,第二个是微信的码,用于登录微信。 63 | 需要注意的是淘宝账号必须认证才能使用淘宝联盟。 64 | 65 | #### 效果图 66 | ![](效果图.png) 67 | 68 | 69 | TODO: 70 | - [] GUI 71 | - [] 更好的错误反馈 72 | - [] 可配置 73 | 74 | 75 | 欢迎大家提issue -------------------------------------------------------------------------------- /libs/utils.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xsren 4 | @contact: bestrenxs@gmail.com 5 | @site: xsren.me 6 | 7 | @version: 1.0 8 | @license: Apache Licence 9 | @file: utils.py 10 | @time: 29/10/2017 5:24 PM 11 | 12 | """ 13 | import logging 14 | 15 | 16 | class ColoredFormatter(logging.Formatter): 17 | def __init__(self, fmt=None): 18 | logging.Formatter.__init__(self, fmt=fmt) 19 | 20 | def format(self, record): 21 | COLORS = { 22 | 'Black': '0;30', 23 | 'Red': '0;31', 24 | 'Green': '0;32', 25 | 'Brown': '0;33', 26 | 'Blue': '0;34', 27 | 'Purple': '0;35', 28 | 'Cyan': '0;36', 29 | 'Light_Gray': '0;37', 30 | 31 | 'Dark_Gray': '1;30', 32 | 'Light_Red': '1;31', 33 | 'Light_Green': '1;32', 34 | 'Yellow': '1;33', 35 | 'Light_Blue': '1;34', 36 | 'Light_Purple': '1;35', 37 | 'Light_Cyan': '1;36', 38 | 'White': '1;37', 39 | } 40 | COLOR_SEQ = "\033[%sm" 41 | RESET_SEQ = "\033[0m" 42 | 43 | message = logging.Formatter.format(self, record) 44 | 45 | if record.levelno == logging.DEBUG: 46 | message = COLOR_SEQ % COLORS['White'] + message + RESET_SEQ 47 | elif record.levelno == logging.INFO: 48 | message = COLOR_SEQ % COLORS['Green'] + message + RESET_SEQ 49 | pass 50 | elif record.levelno == logging.WARNING: 51 | message = COLOR_SEQ % COLORS['Brown'] + message + RESET_SEQ 52 | elif record.levelno == logging.ERROR: 53 | message = COLOR_SEQ % COLORS['Red'] + message + RESET_SEQ 54 | elif record.levelno == logging.CRITICAL: 55 | message = COLOR_SEQ % COLORS['Purple'] + message + RESET_SEQ 56 | return message 57 | 58 | 59 | import logging.handlers 60 | 61 | 62 | def init_logger(): 63 | logger = logging.getLogger("run_parse_url_server") 64 | logger.setLevel(logging.DEBUG) 65 | 66 | # file 67 | log_file_name = "run_parse_url_server.log" 68 | fh = logging.handlers.RotatingFileHandler(log_file_name, maxBytes=1024 * 1024 * 600, backupCount=3) 69 | color_formatter = ColoredFormatter(fmt='%(asctime)s %(funcName)s[line:%(lineno)d] [%(levelname)s]: %(message)s') 70 | fh.setFormatter(color_formatter) 71 | fh.setLevel(logging.DEBUG) 72 | logger.addHandler(fh) 73 | 74 | # stdout 75 | sh = logging.StreamHandler() 76 | color_formatter = ColoredFormatter(fmt='%(asctime)s %(funcName)s[line:%(lineno)d] [%(levelname)s]: %(message)s') 77 | sh.setFormatter(color_formatter) 78 | sh.setLevel(logging.DEBUG) 79 | logger.addHandler(sh) 80 | 81 | return logger 82 | 83 | 84 | def run(): 85 | pass 86 | 87 | 88 | if __name__ == '__main__': 89 | run() 90 | -------------------------------------------------------------------------------- /libs/wx_bot.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xsren 4 | @contact: bestrenxs@gmail.com 5 | @site: xsren.me 6 | 7 | @version: 1.0 8 | @license: Apache Licence 9 | @file: wx_bot.py 10 | @time: 2017/5/28 上午10:40 11 | 12 | """ 13 | from __future__ import unicode_literals 14 | 15 | import platform 16 | import re 17 | import sys 18 | import threading 19 | import traceback 20 | 21 | import itchat 22 | import requests 23 | from itchat.content import * 24 | from libs import utils 25 | from libs.alimama import Alimama 26 | 27 | logger = utils.init_logger() 28 | 29 | al = Alimama(logger) 30 | res = al.login() 31 | if res == "login failed": 32 | sys.exit(0) 33 | 34 | 35 | # 检查是否是淘宝链接 36 | def check_if_is_tb_link(msg): 37 | if re.search(r'【.*】', msg.text) and ( 38 | u'打开👉手机淘宝👈' in msg.text or u'打开👉天猫APP👈' in msg.text or u'打开👉手淘👈' in msg.text or u'👉淘♂寳♀👈' in msg.text): 39 | try: 40 | logger.debug(msg.text) 41 | q = re.search(r'【.*】', msg.text).group().replace(u'【', '').replace(u'】', '') 42 | if u'打开👉天猫APP👈' in msg.text: 43 | try: 44 | url = re.search(r'https://.* ',msg.text).group() 45 | except: 46 | url = None 47 | taokouling = re.search(r'¥.*?¥', msg.text).group() 48 | elif u'👉淘♂寳♀👈' in msg.text: 49 | try: 50 | url = re.search(r'https://.* ',msg.text).group() 51 | except: 52 | url = None 53 | taokouling = re.search(r'€.*?€', msg.text) 54 | 55 | else: 56 | try: 57 | url = re.search(r'https://.* ',msg.text).group() 58 | except: 59 | url = None 60 | # 20170909新版淘宝分享中没有链接, 感谢网友jindx0713(https://github.com/jindx0713)提供代码和思路,现在使用第三方网站 http://www.taokouling.com 根据淘口令获取url 61 | if url is None: 62 | taokoulingurl = 'http://www.taokouling.com/index.php?m=api&a=taokoulingjm' 63 | parms = {'username': 'wx_tb_fanli', 'password': 'wx_tb_fanli', 'text': taokouling} 64 | res = requests.post(taokoulingurl, data=parms) 65 | url = res.json()['url'].replace('https://', 'http://') 66 | info = "tkl url: {}".format(url) 67 | logger.debug(info) 68 | if url == "": 69 | info = u'''%s 70 | ----------------- 71 | 该宝贝暂时没有找到内部返利通道!亲您可以换个宝贝试试,也可以联系我们群内管理员帮着寻找有返现的类似商品 72 | ''' % q 73 | msg.user.send(info) 74 | return 75 | 76 | # get real url 77 | real_url = al.get_real_url(url) 78 | info = "real_url: {}".format(real_url) 79 | logger.debug(info) 80 | 81 | # get detail 82 | res = al.get_detail(real_url) 83 | auctionid = res['auctionId'] 84 | coupon_amount = res['couponAmount'] 85 | tk_rate = res['tkRate'] 86 | price = res['zkPrice'] 87 | fx = (price - coupon_amount) * tk_rate / 100 88 | 89 | # get tk link 90 | res1 = al.get_tk_link(auctionid) 91 | tao_token = res1['taoToken'] 92 | short_link = res1['shortLinkUrl'] 93 | coupon_link = res1['couponLink'] 94 | 95 | if coupon_link != "": 96 | coupon_token = res1['couponLinkTaoToken'] 97 | res_text = ''' 98 | %s 99 | 【返现】%.2f 100 | 【优惠券】%s元 101 | 请复制%s淘口令、打开淘宝APP下单 102 | ----------------- 103 | 【下单地址】%s 104 | ''' % (q, fx, coupon_amount, coupon_token, short_link) 105 | # res_text = u'''%s 106 | # 【优惠券】%s元 107 | # 请复制%s淘口令、打开淘宝APP下单 108 | # ----------------- 109 | # 【下单地址】%s 110 | # ''' % (q, coupon_amount, coupon_token, short_link) 111 | else: 112 | # res_text = u'''%s 113 | # 【优惠券】%s元 114 | # 请复制%s淘口令、打开淘宝APP下单 115 | # ----------------- 116 | # 【下单地址】%s 117 | # ''' % (q, coupon_amount, tao_token, short_link) 118 | res_text = ''' 119 | %s 120 | 【返现】%.2f元 121 | 【优惠券】%s元 122 | 请复制%s淘口令、打开淘宝APP下单 123 | ----------------- 124 | 【下单地址】%s 125 | ''' % (q, fx, coupon_amount, tao_token, short_link) 126 | msg.user.send(res_text) 127 | except Exception as e: 128 | trace = traceback.format_exc() 129 | logger.warning("error:{},trace:{}".format(str(e), trace)) 130 | info = u'''%s 131 | ----------------- 132 | 该宝贝暂时没有找到内部返利通道!亲您可以换个宝贝试试,也可以联系我们群内管理员帮着寻找有返现的类似商品 133 | ''' % q 134 | msg.user.send(info) 135 | 136 | 137 | class WxBot(object): 138 | @itchat.msg_register([TEXT]) 139 | def text_reply(msg): 140 | print(msg.text) 141 | check_if_is_tb_link(msg) 142 | # msg.user.send('%s: %s' % (msg.type, msg.text)) 143 | 144 | @itchat.msg_register(TEXT, isGroupChat=True) 145 | def text_reply(msg): 146 | check_if_is_tb_link(msg) 147 | # if msg.isAt: 148 | # msg.user.send(u'@%s\u2005I received: %s' % ( 149 | # msg.actualNickName, msg.text)) 150 | 151 | def run(self): 152 | sysstr = platform.system() 153 | if (sysstr == "Linux") or (sysstr == "Darwin"): 154 | # itchat.auto_login(enableCmdQR=2, hotReload=True) 155 | itchat.auto_login(hotReload=True) 156 | else: 157 | itchat.auto_login(hotReload=True) 158 | itchat.run(True) 159 | 160 | 161 | if __name__ == '__main__': 162 | mi = WxBot() 163 | t = threading.Thread(target=mi.run, args=()) 164 | t.start() 165 | -------------------------------------------------------------------------------- /libs/alimama.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xsren 4 | @contact: bestrenxs@gmail.com 5 | @site: xsren.me 6 | 7 | @version: 1.0 8 | @license: Apache Licence 9 | @file: alimama.py 10 | @time: 2017/5/27 下午9:55 11 | 12 | """ 13 | import json 14 | import os.path 15 | import platform 16 | import re 17 | import sys 18 | import time 19 | import traceback 20 | from selenium import webdriver 21 | from selenium.webdriver.common.desired_capabilities import DesiredCapabilities 22 | from selenium.webdriver.common.action_chains import ActionChains 23 | 24 | if sys.version_info[0] < 3: 25 | import urllib 26 | else: 27 | import urllib.parse as urllib 28 | 29 | from io import BytesIO 30 | from threading import Thread 31 | 32 | import pyqrcode 33 | import requests 34 | 35 | from PIL import Image 36 | 37 | sysstr = platform.system() 38 | if (sysstr == "Linux") or (sysstr == "Darwin"): 39 | pass 40 | cookie_fname = 'cookies.txt' 41 | 42 | class Alimama: 43 | def __init__(self, logger): 44 | self.se = requests.session() 45 | self.load_cookies() 46 | self.myip = "127.0.0.1" 47 | #self.start_keep_cookie_thread() 48 | self.logger = logger 49 | 50 | # 启动一个线程,定时访问淘宝联盟主页,防止cookie失效 51 | def start_keep_cookie_thread(self): 52 | t = Thread(target=self.visit_main_url, args=()) 53 | t.setDaemon(True) 54 | t.start() 55 | 56 | def visit_main_url(self): 57 | url = "https://pub.alimama.com/" 58 | headers = { 59 | 'method': 'GET', 60 | 'authority': 'pub.alimama.com', 61 | 'scheme': 'https', 62 | 'path': '/common/getUnionPubContextInfo.json', 63 | 'Accept': 'application/json, text/javascript, */*; q=0.01', 64 | 'X-Requested-With': 'XMLHttpRequest', 65 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 66 | 'Referer': 'http://pub.alimama.com/', 67 | 'Accept-Encoding': 'gzip, deflate, sdch', 68 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 69 | } 70 | while True: 71 | time.sleep(60 * 5) 72 | try: 73 | self.logger.debug( 74 | "visit_main_url......,time:{}".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))) 75 | self.get_url(url, headers) 76 | self.logger.debug(self.check_login()) 77 | real_url = "https://detail.tmall.com/item.htm?id=42485910384" 78 | res = self.get_detail(real_url) 79 | auctionid = res['auctionId'] 80 | self.logger.debug(self.get_tk_link(auctionid)) 81 | except Exception as e: 82 | trace = traceback.format_exc() 83 | self.logger.warning("error:{},trace:{}".format(str(e), trace)) 84 | 85 | def get_url(self, url, headers): 86 | res = self.se.get(url, headers=headers) 87 | return res 88 | 89 | def post_url(self, url, headers, data): 90 | res = self.se.post(url, headers=headers, data=data) 91 | return res 92 | 93 | 94 | def load_cookies(self): 95 | # 设置cookie 96 | if os.path.isfile(cookie_fname): 97 | with open(cookie_fname, 'r') as f: 98 | c_str = f.read().strip() 99 | self.set_cookies(c_str) 100 | 101 | def set_cookies(self, c_str): 102 | try: 103 | cookies = json.loads(c_str) 104 | except: 105 | print('error cookie') 106 | for k,v in cookies.items(): 107 | self.se.cookies.set(k, v) 108 | 109 | # check login 110 | def check_login(self): 111 | self.logger.debug('checking login status.....') 112 | url = 'https://pub.alimama.com/common/getUnionPubContextInfo.json' 113 | headers = { 114 | 'method': 'GET', 115 | 'authority': 'pub.alimama.com', 116 | 'scheme': 'https', 117 | 'path': '/common/getUnionPubContextInfo.json', 118 | 'Accept': 'application/json, text/javascript, */*; q=0.01', 119 | 'X-Requested-With': 'XMLHttpRequest', 120 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 121 | 'Referer': 'http://pub.alimama.com/', 122 | 'Accept-Encoding': 'gzip, deflate, sdch', 123 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 124 | } 125 | 126 | res = self.get_url(url, headers=headers) 127 | rj = json.loads(res.text) 128 | return rj 129 | 130 | def login(self): 131 | try: 132 | clr = self.check_login() 133 | self.myip = clr['data']['ip'] 134 | if 'mmNick' in clr['data']: 135 | self.logger.debug(u"淘宝已经登录 不需要再次登录") 136 | return 'login success' 137 | else: 138 | print(u"请更新最新的cookie到cookies_taobao.txt文件中!!!") 139 | raise Exception("need to refresh taobao cookie") 140 | dlr = self.do_login() 141 | if dlr is None: 142 | return 'login failed' 143 | else: 144 | return 'login success' 145 | except Exception as e: 146 | # trace = traceback.format_exc() 147 | # self.logger.warning(u"{},{}".format(str(e), trace)) 148 | print(u"淘宝登录失败") 149 | return 'login failed' 150 | 151 | def new_login(self): 152 | self.driver = webdriver.Ie() 153 | self.driver.get("https://login.taobao.com/member/login.jhtml?style=mini&newMini2=true&from=alimama&redirectURL=http%3A%2F%2Flogin.taobao.com%2Fmember%2Ftaobaoke%2Flogin.htm%3Fis_login%3d1&full_redirect=true") 154 | login_button = self.driver.find_element_by_id('J_SubmitQuick') 155 | login_button.click() 156 | time.sleep(1) 157 | # self.driver.save_screenshot('login-screeshot-1.png') 158 | cookies = {item["name"]: item["value"] for item in self.driver.get_cookies()} 159 | with open(cookie_fname, 'w') as f: 160 | f.write(json.dumps(cookies)) 161 | time.sleep(2) 162 | return 'login success' 163 | 164 | def get_tb_token(self): 165 | tb_token = None 166 | for c in self.se.cookies.items(): 167 | if c[0] == '_tb_token_': 168 | return c[1] 169 | if tb_token is None: 170 | return 'test' 171 | 172 | # 获取商品详情 173 | def get_detail(self, q): 174 | try: 175 | t = int(time.time() * 1000) 176 | tb_token = self.get_tb_token() 177 | pvid = '10_%s_1686_%s' % (self.myip, t) 178 | url = 'http://pub.alimama.com/items/search.json?q=%s&_t=%s&auctionTag=&perPageSize=40&shopTag=&t=%s&_tb_token_=%s&pvid=%s' % ( 179 | urllib.quote(q.encode('utf8')), t, t, tb_token, pvid) 180 | headers = { 181 | 'method': 'GET', 182 | 'authority': 'pub.alimama.com', 183 | 'scheme': 'https', 184 | 'path': '/items/search.json?%s' % url.split('search.json?')[-1], 185 | 'accept': 'application/json, text/javascript, */*; q=0.01', 186 | 'x-requested-with': 'XMLHttpRequest', 187 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 188 | 'referer': 'https://pub.alimama.com', 189 | 'accept-encoding': 'gzip, deflate, sdch, br', 190 | 'accept-language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 191 | } 192 | res = self.get_url(url, headers) 193 | rj = res.json() 194 | if len(rj['data']['pageList']) > 0: 195 | return rj['data']['pageList'][0] 196 | else: 197 | return 'no match item' 198 | except Exception as e: 199 | trace = traceback.format_exc() 200 | self.logger.warning("error:{},trace:{}".format(str(e), trace)) 201 | 202 | # 获取淘宝客链接 203 | def get_tk_link(self, auctionid): 204 | t = int(time.time() * 1000) 205 | tb_token = self.get_tb_token() 206 | pvid = '10_%s_1686_%s' % (self.myip, t) 207 | try: 208 | gcid, siteid, adzoneid = self.__get_tk_link_s1(auctionid, tb_token, pvid) 209 | self.__get_tk_link_s2(gcid, siteid, adzoneid, auctionid, tb_token, pvid) 210 | res = self.__get_tk_link_s3(auctionid, adzoneid, siteid, tb_token, pvid) 211 | return res 212 | except Exception as e: 213 | trace = traceback.format_exc() 214 | self.logger.warning("error:{},trace:{}".format(str(e), trace)) 215 | 216 | # 第一步,获取推广位相关信息 217 | def __get_tk_link_s1(self, auctionid, tb_token, pvid): 218 | url = 'http://pub.alimama.com/common/adzone/newSelfAdzone2.json?tag=29&itemId=%s&blockId=&t=%s&_tb_token_=%s&pvid=%s' % ( 219 | auctionid, int(time.time() * 1000), tb_token, pvid) 220 | headers = { 221 | 'Host': 'pub.alimama.com', 222 | 'Accept': 'application/json, text/javascript, */*; q=0.01', 223 | 'X-Requested-With': 'XMLHttpRequest', 224 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 225 | 'Referer': 'http://pub.alimama.com/promo/search/index.htm', 226 | 'Accept-Encoding': 'gzip, deflate, sdch', 227 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 228 | } 229 | res = self.get_url(url, headers) 230 | self.logger.debug(res.text) 231 | rj = res.json() 232 | gcid = rj['data']['otherList'][0]['gcid'] 233 | siteid = rj['data']['otherList'][0]['siteid'] 234 | adzoneid = rj['data']['otherAdzones'][0]['sub'][0]['id'] 235 | return gcid, siteid, adzoneid 236 | 237 | # post数据 238 | def __get_tk_link_s2(self, gcid, siteid, adzoneid, auctionid, tb_token, pvid): 239 | url = 'http://pub.alimama.com/common/adzone/selfAdzoneCreate.json' 240 | data = { 241 | 'tag': '29', 242 | 'gcid': gcid, 243 | 'siteid': siteid, 244 | 'selectact': 'sel', 245 | 'adzoneid': adzoneid, 246 | 't': int(time.time() * 1000), 247 | '_tb_token_': tb_token, 248 | 'pvid': pvid, 249 | } 250 | headers = { 251 | 'Host': 'pub.alimama.com', 252 | 'Content-Length': str(len(json.dumps(data))), 253 | 'Accept': 'application/json, text/javascript, */*; q=0.01', 254 | 'Origin': 'http://pub.alimama.com', 255 | 'X-Requested-With': 'XMLHttpRequest', 256 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 257 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 258 | 'Referer': 'http://pub.alimama.com/promo/search/index.htm', 259 | 'Accept-Encoding': 'gzip, deflate', 260 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 261 | } 262 | 263 | res = self.post_url(url, headers, data) 264 | return res 265 | 266 | # 获取口令 267 | def __get_tk_link_s3(self, auctionid, adzoneid, siteid, tb_token, pvid): 268 | url = 'http://pub.alimama.com/common/code/getAuctionCode.json?auctionid=%s&adzoneid=%s&siteid=%s&scenes=1&t=%s&_tb_token_=%s&pvid=%s' % ( 269 | auctionid, adzoneid, siteid, int(time.time() * 1000), tb_token, pvid) 270 | headers = { 271 | 'Host': 'pub.alimama.com', 272 | 'Accept': 'application/json, text/javascript, */*; q=0.01', 273 | 'X-Requested-With': 'XMLHttpRequest', 274 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 275 | 'Referer': 'http://pub.alimama.com/promo/search/index.htm', 276 | 'Accept-Encoding': 'gzip, deflate, sdch', 277 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 278 | } 279 | res = self.get_url(url, headers) 280 | rj = json.loads(res.text) 281 | try: 282 | self.driver.quit() 283 | except: 284 | print('ok,go on') 285 | return rj['data'] 286 | 287 | def get_real_url(self, url): 288 | # return "https://detail.tmall.com/item.htm?id=548726815314" 289 | try: 290 | headers = { 291 | 'Host': url.split('https://')[-1].split('/')[0], 292 | 'Upgrade-Insecure-Requests': '1', 293 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 294 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 295 | 'Accept-Encoding': 'gzip, deflate, sdch', 296 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 297 | } 298 | res = self.get_url(url, headers) 299 | if re.search(r'itemId\":\d+', res.text): 300 | item_id = re.search(r'itemId\":\d+', res.text).group().replace('itemId":', '').replace('https://','http://') 301 | r_url = "https://detail.tmall.com/item.htm?id=%s" % item_id 302 | elif re.search(r"var url = '.*';", res.text): 303 | r_url = re.search(r"var url = '.*';", res.text).group().replace("var url = '", "").replace("';","").replace('https://', 'http://') 304 | else: 305 | r_url = res.url 306 | if 's.click.taobao.com' in r_url: 307 | r_url = self.handle_click_type_url(r_url) 308 | elif 'm.intl.taobao.com' in r_url: 309 | item_id = re.search(r'item_id=\d+', text).group().replace('item_id=', '') 310 | r_url = "https://item.taobao.com/item.htm?id=%s" % item_id 311 | else: 312 | while ('detail.tmall.com' not in r_url) and ('item.taobao.com' not in r_url) and ('detail.m.tmall.com' not in r_url): 313 | headers1 = { 314 | 'Host': r_url.split('http://')[-1].split('/')[0], 315 | 'Upgrade-Insecure-Requests': '1', 316 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 317 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 318 | 'Accept-Encoding': 'gzip, deflate, sdch', 319 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 320 | } 321 | res2 = self.get_url(r_url, headers1) 322 | self.logger.debug("{},{},{}".format(res2.url, res2.status_code, res2.history)) 323 | r_url = res2.url 324 | 325 | self.logger.debug(r_url) 326 | return r_url 327 | except Exception as e: 328 | self.logger.warning(str(e)) 329 | return url 330 | 331 | def handle_click_type_url(self, url): 332 | # step 1 333 | headers = { 334 | 'method': 'GET', 335 | 'authority': 's.click.taobao.com', 336 | 'scheme': 'https', 337 | 'path': '/t?%s' % url.split('/t?')[-1], 338 | 'Upgrade-Insecure-Requests': '1', 339 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 340 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 341 | 'Accept-Encoding': 'gzip, deflate, sdch', 342 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 343 | } 344 | res = self.get_url(url, headers) 345 | self.logger.debug("{},{},{}".format(res.url, res.status_code, res.history)) 346 | url2 = res.url 347 | 348 | # step 2 349 | headers2 = { 350 | 'referer': url, 351 | 'method': 'GET', 352 | 'authority': 's.click.taobao.com', 353 | 'scheme': 'https', 354 | 'path': '/t?%s' % url2.split('/t?')[-1], 355 | 'Upgrade-Insecure-Requests': '1', 356 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 357 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 358 | 'Accept-Encoding': 'gzip, deflate, sdch', 359 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 360 | } 361 | res2 = self.get_url(url2, headers2) 362 | self.logger.debug("{},{},{}".format(res2.url, res2.status_code, res2.history)) 363 | url3 = urllib.unquote(res2.url.split('t_js?tu=')[-1]) 364 | 365 | # step 3 366 | headers3 = { 367 | 'referer': url2, 368 | 'method': 'GET', 369 | 'authority': 's.click.taobao.com', 370 | 'scheme': 'https', 371 | 'path': '/t?%s' % url3.split('/t?')[-1], 372 | 'Upgrade-Insecure-Requests': '1', 373 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 374 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 375 | 'Accept-Encoding': 'gzip, deflate, sdch', 376 | 'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2', 377 | } 378 | res3 = self.get_url(url3, headers3) 379 | self.logger.debug("{},{},{}".format(res3.url, res3.status_code, res3.history)) 380 | r_url = res3.url 381 | 382 | return r_url 383 | 384 | 385 | if __name__ == '__main__': 386 | al = Alimama() 387 | # al.login() 388 | # q = u'现货 RS版 树莓派3代B型 Raspberry Pi 3B 板载wifi和蓝牙' 389 | # q = u'蔻斯汀玫瑰身体护理套装沐浴露身体乳爽肤水滋润全身保湿补水正品' 390 | # q = u'DIY个性定制T恤 定做工作服短袖 男女夏季纯棉广告文化衫Polo印制' 391 | q = u'防晒衣女2017女装夏装新款印花沙滩防晒服薄中长款大码白色短外套' 392 | # res = al.get_detail(q) 393 | # auctionid = res['auctionId'] 394 | # al.get_tk_link(auctionid) 395 | # url = 'http://c.b1wt.com/h.SQwr1X?cv=kzU8ZvbiEa8&sm=796feb' 396 | # al.get_real_url(url) 397 | # url = 'http://c.b1wt.com/h.S9fQZb?cv=zcNtZvbH4ak&sm=79e4be' 398 | # al.get_real_url(url) 399 | # url = 'http://c.b1wt.com/h.S9gdyy?cv=RW5EZvbuYBw&sm=231894' 400 | # al.get_real_url(url) 401 | # url = 'http://c.b1wt.com/h.S8ppn7?cv=ObUrZvZ3oH9&sm=1b02f8' 402 | # al.get_real_url(url) 403 | # url = 'http://c.b1wt.com/h.SQ70kv?cv=L5HpZv0w4hJ' 404 | # url = 'http://c.b1wt.com/h.S9A0pK?cv=8grnZvYkU14&sm=efb5b7' 405 | url = 'http://zmnxbc.com/s/nlO3j?tm=95b078' 406 | al.get_real_url(url) 407 | --------------------------------------------------------------------------------