from FileUtil import *from OtherUtil import *from RequestUtil import *from selenium import webdriverclass JdHelper:    def __init__(self, need_type, filter_list, is_reverse_filter, user_name, user_pwd):        self.not_apply_list = []  # 忽略种草官商品        self.user_name = user_name        self.user_pwd = user_pwd        self.cookie_file = "cookie.txt"        self.not_apply_file = "notApply.txt"        self.wait_apply_list = []  # 待申请列表        self.session = requests.session()        self.headers = {            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36",            "Referer": "https://try.jd.com/activity/getActivityList?page=1&cids=737",        }        self.count = 0        self.base_url_list = {            "家用电器": "https://try.jd.com/activity/getActivityList?activityState=0&cids=737",            "手机数码": "https://try.jd.com/activity/getActivityList?activityState=0&cids=652,9987",            "电脑办公": "https://try.jd.com/activity/getActivityList?activityState=0&cids=670",            "家居家装": "https://try.jd.com/activity/getActivityList?activityState=0&cids=1620,6728,9847,9855,6196,15248,14065",            "美妆护肤": "https://try.jd.com/activity/getActivityList?activityState=0&cids=1316",            "服饰鞋包": "https://try.jd.com/activity/getActivityList?activityState=0&cids=1315,1672,1318,11729",            "母婴玩具": "https://try.jd.com/activity/getActivityList?activityState=0&cids=1319,6233",            "生鲜美食": "https://try.jd.com/activity/getActivityList?activityState=0&cids=12218",            "图书音像": "https://try.jd.com/activity/getActivityList?activityState=0&cids=1713,4051,4052,4053,7191,7192,5272",            "钟表奢品": "https://try.jd.com/activity/getActivityList?activityState=0&cids=5025,6144",            "个人护理": "https://try.jd.com/activity/getActivityList?activityState=0&cids=16750",            "家庭清洁": "https://try.jd.com/activity/getActivityList?activityState=0&cids=15901",            "食品饮料": "https://try.jd.com/activity/getActivityList?activityState=0&cids=1320,12259",            "更多惊喜": "https://try.jd.com/activity/getActivityList?activityState=0&cids=4938,13314,6994,9192,12473,6196,5272,12379,13678,15083,15126,15980"        }        self.not_apply()        if not self.check_login():            LoginHelper().login(self.user_name, self.user_pwd)            self.check_login()        self.sum()        # 是否反转过滤 True:商品名必须包含在filter_list  False:商品名不能包含在filter_list        self.is_reverse_filter = is_reverse_filter        self.filter_list = filter_list        self.need_type = need_type        if self.is_reverse_filter:            print("入选词汇:", self.filter_list)        else:            print("过滤词汇:", self.filter_list)    @retry(stop_max_attempt_number=20)    def get_resp(self, url):        return self.session.get(url, headers=self.headers, timeout=3)    # 查询是否已申请    def getApplyStateByActivityIds(self, activityIds):        url = "https://try.jd.com/user/getApplyStateByActivityIds?activityIds=" + activityIds        resp = self.get_resp(url)        for item in resp.json():            obj = self.find_obj(item["activityId"])            if obj:                self.wait_apply_list.remove(obj)    # 过滤list    def find_obj(self, id):        for data in self.wait_apply_list:            if str(id) == str(data["activity_id"]):                return data    # 申请    def apply(self):        can_stop = False        for wait_apply in self.wait_apply_list:            print("\n正在申请,", wait_apply["activity_id"], wait_apply["name"])            # 获取店铺id            activity_id = wait_apply["activity_id"]            item_url = "https://try.jd.com/{}.html".format(activity_id)            shop_id = re.findall('id="_shopId" value="(.*?)"', self.get_resp(item_url).text)[0]            time.sleep(1)            # 关注            follow_url = "https://try.jd.com/migrate/follow?_s=pc&venderId={}".format(shop_id)            resp = self.get_resp(follow_url)            print(resp.json())            time.sleep(2)            # 申请            url = "https://try.jd.com/migrate/apply?activityId={}&source=0".format(activity_id)            resp = self.get_resp(url)            resp_data = resp.json()            print(resp_data)            if resp_data["success"]:                self.count += 1                print("当天已申请次数:", self.count)            elif '种草官' in resp_data["message"]:                with open("notApply.txt", encoding="utf-8", mode="a+") as f:                    f.write(activity_id + "\n")            elif '超过' in resp_data["message"] or '已超' in resp_data["message"]:                self.cancel_follow_item()                self.cancel_follow_shop()                can_stop = True                break            time.sleep(3)        return can_stop    # 获取页面大小    def get_page_size(self, url):        resp = self.get_resp(url)        return int(re.findall('"pages":(\d+)', resp.text)[0])    # 检查登录状态    def check_login(self):        self.set_cookie()        url = "https://passport.jd.com/user/petName/getUserInfoForMiniJd.action"        resp = self.get_resp(url)        if 'null' in resp.text:            print("cookie失效, 返回信息:", resp.text)            return False        else:            print("登录成功, 当前用户名:", resp.json()["nickName"])            return True    # 读取并设置cookie    def set_cookie(self):        if os.path.exists(self.cookie_file):            with open(self.cookie_file, encoding="utf-8", mode="r") as f:                self.headers["Cookie"] = f.read().strip()    # 统计今日已申请次数    def sum(self):        page = 1        run = True        today = time.strftime("%Y-%m-%d")        while run:            url = "https://try.jd.com/user/myTrial?page={}".format(page)            resp = self.get_resp(url)            parser = etree.HTML(resp.text)            day_list = parser.xpath('//span[@class="time"]/em/text()')            for day in day_list:                if today in day:                    self.count += 1                else:                    run = False            page += 1        print("今日已申请次数:", self.count)    # 过滤器    def in_filter_list(self, name):        has_find = True        for filter in self.filter_list:            if filter in name:                has_find = False        if self.is_reverse_filter:            has_find = not has_find        return has_find    # 过滤种草官级别    def not_apply(self):        if os.path.exists(self.not_apply_file):            with open(self.not_apply_file, encoding="utf-8", mode="r") as f:                for line in f.readlines():                    self.not_apply_list.append(line.strip())    # 取关商品    def cancel_follow_item(self):        can_run = True        while can_run:            page_url = "https://t.jd.com/home/follow?index=1"            resp = self.get_resp(page_url)            parser = etree.HTML(resp.text)            item_id_list = ""            for item in parser.xpath('//*[@id="main"]/div/div[2]/div[2]/div[1]/div'):                if not item.xpath("./@id"):                    print("当前没有需要取关的商品")                    can_run = False                    break                item_id_list += item.xpath("./@id")[0].replace('goods_', '') + ","            item_id_list = item_id_list[0:-1]            url = "https://api.m.jd.com/api?functionId=batchCancelFavorite&body={%22skus%22:%22" + item_id_list + "%22}&appid=follow_for_concert&soaKey=2e2i4fRvyfAek5MfHNCe;fMeBpvzbQimFgonJp9YpBqyMcz1VvO4sWcyIBRb8VdOTNQDVo7&client=pc&t=1627133437064&jsonp=result&_=1627133437064"            resp = self.get_resp(url)            print(resp.text)    # 取关店铺    def cancel_follow_shop(self):        can_run = True        while can_run:            page_url = "https://t.jd.com/follow/vender/list.do"            resp = self.get_resp(page_url)            re_list = re.findall('id="vender_(.*?)"', resp.text)            if not re_list:                print("当前没有需要取关的店铺")                break            shop_id_list = ""            for item in re_list:                shop_id_list += item + ","            shop_id_list = shop_id_list[0:-1]            url = "https://t.jd.com/follow/vender/batchUnfollow.do"            resp = self.session.post(url, data={"venderIds": shop_id_list}, headers=self.headers)            print(resp.text)    def run(self):        can_stop = False        for need in self.need_type:            base_url = self.base_url_list[need]            page_size = self.get_page_size(base_url)            print("当前类型:{} 总页数:{}".format(need, page_size))            if can_stop:                break            for i in range(1, page_size + 1):                self.wait_apply_list = []                url = base_url + "&page={}".format(i)                print("\n获取第{}页 总页数:{} {}".format(i, page_size, url))                resp = self.get_resp(url)                parser = etree.HTML(resp.text)                activityIds = []  # 查询是否已申请                item_list = parser.xpath('//*[@id="goods-list"]/div[2]/div/ul/li')                for item in item_list:                    wait_apply = {}                    activity_id = item.xpath("./@activity_id")[0]                    activityIds.append(activity_id)                    wait_apply["activity_id"] = activity_id                    wait_apply["name"] = item.xpath(".//div[@class='p-name']/text()")[0].strip()                    if activity_id in self.not_apply_list:                        print("该申请需种草官要求,跳过", wait_apply["name"])                        continue                    if self.in_filter_list(wait_apply["name"]):                        print("加入待申请:", wait_apply["name"])                        self.wait_apply_list.append(wait_apply)                    else:                        print("该商品已被过滤:", wait_apply["name"])                        continue                self.getApplyStateByActivityIds(",".join(activityIds))                can_stop = self.apply()                if can_stop:                    break# 模拟登录class LoginHelper:    def login(self, user_name, user_pwd):        chrome_options = webdriver.ChromeOptions()        chrome_options.add_argument('log-level=2')        try:            driver = webdriver.Chrome(options=chrome_options)        except:            driver = webdriver.Chrome(options=chrome_options, executable_path="C:/chromedriver.exe")        driver.get('https://passport.jd.com/new/login.aspx')        driver.find_element_by_css_selector(            '#content > div.login-wrap > div.w > div > div.login-tab.login-tab-r > a').click()        driver.implicitly_wait(2)        input_username = driver.find_element_by_name('loginname')        input_username.send_keys(user_name)        input_password = driver.find_element_by_name('nloginpwd')        input_password.send_keys(user_pwd)        button_logOK = driver.find_elements_by_id('loginsubmit')        button_logOK = button_logOK[0]        button_logOK.click()        while True:            try:                if driver.find_element_by_css_selector('#ttbar-login > div.dt.cw-icon > a'):                    break            except:                print_exc()                time.sleep(1)        print('登陆成功!')        cookie_dict_list = driver.get_cookies()        self.save_cookie(cookie_dict_list)        driver.quit()    def save_cookie(self, cookie_dict_list):        cookies_str = ""        for cookie_dict in cookie_dict_list:            name = cookie_dict["name"]            value = cookie_dict["value"]            cookies_str += name + "=" + value + "; "        cookies_str = cookies_str[0:-2]        with open("cookie.txt", encoding="utf-8", mode="w") as f:            f.write(cookies_str)if __name__ == '__main__':    user_name = "手机账号"    user_pwd = "密码"    need_type = [        "家用电器",        "手机数码",        "电脑办公",        "家居家装",        "美妆护肤",        "服饰鞋包",        "母婴玩具",        "生鲜美食",        "图书音像",        "钟表奢品",        "个人护理",        "家庭清洁",        "食品饮料",    ]    filter_list = [        '电话卡', '流量卡', '电信', '进销存', '贴纸', '书签', '便利贴', '笔', '纸',        '文具', '儿童', '贴画', '除螨', '口罩', '财务', '软件', '马丁靴', '耳罩', '鞋垫', '长虹', '钥匙'        , '系统', '钢化膜', '特雷索', '流量', '卡槽', '手机壳', '手套', '帽子', '指甲', '领带',        '牙刷', '刀', '袜子', '口红', '数据线', '充电器', '茶', '卸妆', '洗脸', '面巾', '毛巾',        '伸缩带', '剂', '灯', '香水', '车贴', '地漏', '雨刷', '胶', '门窗'    ]    jdHelper = JdHelper(need_type, filter_list, False, user_name, user_pwd)    jdHelper.run()