# ============================================================================== # Copyright (C) 2021 Evil0ctal # # This file is part of the Douyin_TikTok_Download_API project. # # This project is licensed under the Apache License 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== #         __ #        />  フ #       |  _  _ l #       /` ミ_xノ #      /      | Feed me Stars ⭐ ️ #     /  ヽ   ノ #     │  | | | #  / ̄|   | | | #  | ( ̄ヽ__ヽ_)__) #  \二つ # ============================================================================== # # Contributor Link: # - https://github.com/Evil0ctal # - https://github.com/Johnserf-Seed # # ============================================================================== import asyncio # 异步I/O import time # 时间操作 import yaml # 配置文件 import os # 系统操作 # 基础爬虫客户端和TikTokAPI端点 from crawlers.base_crawler import BaseCrawler from crawlers.tiktok.web.endpoints import TikTokAPIEndpoints from crawlers.utils.utils import extract_valid_urls # TikTok加密参数生成器 from crawlers.tiktok.web.utils import ( AwemeIdFetcher, BogusManager, SecUserIdFetcher, TokenManager ) # TikTok接口数据请求模型 from crawlers.tiktok.web.models import ( UserProfile, UserPost, UserLike, UserMix, UserCollect, PostDetail, UserPlayList, PostComment, PostCommentReply, UserFans, UserFollow ) # 配置文件路径 path = os.path.abspath(os.path.dirname(__file__)) # 读取配置文件 with open(f"{path}/config.yaml", "r", encoding="utf-8") as f: config = yaml.safe_load(f) class TikTokWebCrawler: def __init__(self): self.proxy_pool = None # 从配置文件中获取TikTok的请求头 async def get_tiktok_headers(self): tiktok_config = config["TokenManager"]["tiktok"] kwargs = { "headers": { "User-Agent": tiktok_config["headers"]["User-Agent"], "Referer": tiktok_config["headers"]["Referer"], "Cookie": tiktok_config["headers"]["Cookie"], }, "proxies": {"http://": None, "https://": None}, } return kwargs """-------------------------------------------------------handler接口列表-------------------------------------------------------""" # 获取单个作品数据 async def fetch_one_video(self, itemId: str): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=kwargs["proxies"], crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个作品详情的BaseModel参数 params = PostDetail(itemId=itemId) # 生成一个作品详情的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.POST_DETAIL, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取用户的个人信息 async def fetch_user_profile(self, secUid: str, uniqueId: str): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=kwargs["proxies"], crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个用户详情的BaseModel参数 params = UserProfile(secUid=secUid, uniqueId=uniqueId) # 生成一个用户详情的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.USER_DETAIL, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取用户的作品列表 async def fetch_user_post(self, secUid: str, cursor: int = 0, count: int = 35, coverFormat: int = 2): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # proxies = {"http://": 'http://43.159.29.191:24144', "https://": 'http://43.159.29.191:24144'} # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=None, crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个用户作品的BaseModel参数 params = UserPost(secUid=secUid, cursor=cursor, count=count, coverFormat=coverFormat) # 生成一个用户作品的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.USER_POST, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取用户的点赞列表 async def fetch_user_like(self, secUid: str, cursor: int = 0, count: int = 30, coverFormat: int = 2): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=kwargs["proxies"], crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个用户点赞的BaseModel参数 params = UserLike(secUid=secUid, cursor=cursor, count=count, coverFormat=coverFormat) # 生成一个用户点赞的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.USER_LIKE, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取用户的收藏列表 async def fetch_user_collect(self, cookie: str, secUid: str, cursor: int = 0, count: int = 30, coverFormat: int = 2): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() kwargs["headers"]["Cookie"] = cookie # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=kwargs["proxies"], crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个用户收藏的BaseModel参数 params = UserCollect(cookie=cookie, secUid=secUid, cursor=cursor, count=count, coverFormat=coverFormat) # 生成一个用户收藏的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.USER_COLLECT, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取用户的播放列表 async def fetch_user_play_list(self, secUid: str, cursor: int = 0, count: int = 30): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=kwargs["proxies"], crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个用户播放列表的BaseModel参数 params = UserPlayList(secUid=secUid, cursor=cursor, count=count) # 生成一个用户播放列表的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.USER_PLAY_LIST, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取用户的合辑列表 async def fetch_user_mix(self, mixId: str, cursor: int = 0, count: int = 30): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=kwargs["proxies"], crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个用户合辑的BaseModel参数 params = UserMix(mixId=mixId, cursor=cursor, count=count) # 生成一个用户合辑的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.USER_MIX, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取作品的评论列表 async def fetch_post_comment(self, aweme_id: str, cursor: int = 0, count: int = 20, current_region: str = ""): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # proxies = {"http://": 'http://43.159.18.174:25263', "https://": 'http://43.159.18.174:25263'} # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=None, crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个作品评论的BaseModel参数 params = PostComment(aweme_id=aweme_id, cursor=cursor, count=count, current_region=current_region) # 生成一个作品评论的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.POST_COMMENT, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取作品的评论回复列表 async def fetch_post_comment_reply(self, item_id: str, comment_id: str, cursor: int = 0, count: int = 20, current_region: str = ""): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=kwargs["proxies"], crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个作品评论的BaseModel参数 params = PostCommentReply(item_id=item_id, comment_id=comment_id, cursor=cursor, count=count, current_region=current_region) # 生成一个作品评论的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.POST_COMMENT_REPLY, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取用户的粉丝列表 async def fetch_user_fans(self, secUid: str, count: int = 30, maxCursor: int = 0, minCursor: int = 0): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=kwargs["proxies"], crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个用户关注的BaseModel参数 params = UserFans(secUid=secUid, count=count, maxCursor=maxCursor, minCursor=minCursor) # 生成一个用户关注的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.USER_FANS, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response # 获取用户的关注列表 async def fetch_user_follow(self, secUid: str, count: int = 30, maxCursor: int = 0, minCursor: int = 0): # 获取TikTok的实时Cookie kwargs = await self.get_tiktok_headers() # 创建一个基础爬虫 base_crawler = BaseCrawler(proxies=kwargs["proxies"], crawler_headers=kwargs["headers"]) async with base_crawler as crawler: # 创建一个用户关注的BaseModel参数 params = UserFollow(secUid=secUid, count=count, maxCursor=maxCursor, minCursor=minCursor) # 生成一个用户关注的带有加密参数的Endpoint endpoint = BogusManager.model_2_endpoint( TikTokAPIEndpoints.USER_FOLLOW, params.dict(), kwargs["headers"]["User-Agent"] ) response = await crawler.fetch_get_json(endpoint) return response """-------------------------------------------------------utils接口列表-------------------------------------------------------""" # 生成真实msToken async def fetch_real_msToken(self): result = { "msToken": TokenManager().gen_real_msToken() } return result # 生成ttwid async def gen_ttwid(self, cookie: str): result = { "ttwid": TokenManager().gen_ttwid(cookie) } return result # 生成xbogus async def gen_xbogus(self, url: str, user_agent: str): url = BogusManager.xb_str_2_endpoint(user_agent, url) result = { "url": url, "x_bogus": url.split("&X-Bogus=")[1], "user_agent": user_agent } return result # 提取单个用户id async def get_sec_user_id(self, url: str): return await SecUserIdFetcher.get_secuid(url) # 提取列表用户id async def get_all_sec_user_id(self, urls: list): # 提取有效URL urls = extract_valid_urls(urls) # 对于URL列表 return await SecUserIdFetcher.get_all_secuid(urls) # 提取单个作品id async def get_aweme_id(self, url: str): return await AwemeIdFetcher.get_aweme_id(url) # 提取列表作品id async def get_all_aweme_id(self, urls: list): # 提取有效URL urls = extract_valid_urls(urls) # 对于URL列表 return await AwemeIdFetcher.get_all_aweme_id(urls) # 获取用户unique_id async def get_unique_id(self, url: str): return await SecUserIdFetcher.get_uniqueid(url) # 获取列表unique_id列表 async def get_all_unique_id(self, urls: list): # 提取有效URL urls = extract_valid_urls(urls) # 对于URL列表 return await SecUserIdFetcher.get_all_uniqueid(urls) """-------------------------------------------------------main接口列表-------------------------------------------------------""" async def main(self): # 获取单个作品数据 # item_id = "7339393672959757570" # response = await self.fetch_one_video(item_id) # print(response) # 获取用户的个人信息 # secUid = "MS4wLjABAAAAfDPs6wbpBcMMb85xkvDGdyyyVAUS2YoVCT9P6WQ1bpuwEuPhL9eFtTmGvxw1lT2C" # uniqueId = "c4shjaz" # response = await self.fetch_user_profile(secUid, uniqueId) # print(response) # 获取用户的作品列表 # secUid = "MS4wLjABAAAAfDPs6wbpBcMMb85xkvDGdyyyVAUS2YoVCT9P6WQ1bpuwEuPhL9eFtTmGvxw1lT2C" # cursor = 0 # count = 35 # coverFormat = 2 # response = await self.fetch_user_post(secUid, cursor, count, coverFormat) # print(response) # 获取用户的点赞列表 # secUid = "MS4wLjABAAAAq1iRXNduFZpY301UkVpJ1eQT60_NiWS9QQSeNqmNQEDJp0pOF8cpleNEdiJx5_IU" # cursor = 0 # count = 30 # coverFormat = 2 # response = await self.fetch_user_like(secUid, cursor, count, coverFormat) # print(response) # 获取用户的收藏列表 # cookie = "ttwid=1%7Cbf2dxDZQ2bEXkDZCxVuIuo_p3DnLZydqkW-M-yEHrQ8%7C1712658199%7C4163e4b82a08fd8160ec7d3959a3c07b2dea47b1184fd4e35619ba732a48c1f7; tt_chain_token=AlPMTLvrUZOd3f21B8dbGQ==; tiktok_webapp_theme=light; odin_tt=70b04a203cd043dbe532561dd854ce106b9c0253acf3c105969313c9f58b97bafd88ba18dd551651e4a4bf92d02067b281ca82d4a75acb17b95d7d39103aa4da0f3597fe75e56404891f651147b9bc3f; passport_csrf_token=fd79484bbdda182d711ad15fa11c059d; passport_csrf_token_default=fd79484bbdda182d711ad15fa11c059d; multi_sids=7262344915936658478%3Aa5b1dc5805dee79797d4470ffa822e45; cmpl_token=AgQQAPNSF-RO0rT35p6-9h0X_5yvjXFav6jZYNCqgQ; sid_guard=a5b1dc5805dee79797d4470ffa822e45%7C1711264624%7C15552000%7CFri%2C+20-Sep-2024+07%3A17%3A04+GMT; uid_tt=59c2975ea05dc11e9f7f548a658d65348935cb555d188c432fe2e5d0bd6b75e1; uid_tt_ss=59c2975ea05dc11e9f7f548a658d65348935cb555d188c432fe2e5d0bd6b75e1; sid_tt=a5b1dc5805dee79797d4470ffa822e45; sessionid=a5b1dc5805dee79797d4470ffa822e45; sessionid_ss=a5b1dc5805dee79797d4470ffa822e45; sid_ucp_v1=1.0.0-KDNkZDkzMWRkNzMwOTU4NWVjZWNjZDAxZGE0NDgyNDJlYWQ3MTU4YjcKIAiuiJO2k4fC5GQQ8Kb_rwYYswsgDDDCkaSmBjgBQOoHEAQaB3VzZWFzdDUiIGE1YjFkYzU4MDVkZWU3OTc5N2Q0NDcwZmZhODIyZTQ1; ssid_ucp_v1=1.0.0-KDNkZDkzMWRkNzMwOTU4NWVjZWNjZDAxZGE0NDgyNDJlYWQ3MTU4YjcKIAiuiJO2k4fC5GQQ8Kb_rwYYswsgDDDCkaSmBjgBQOoHEAQaB3VzZWFzdDUiIGE1YjFkYzU4MDVkZWU3OTc5N2Q0NDcwZmZhODIyZTQ1; store-idc=useast5; store-country-code=us; store-country-code-src=uid; tt-target-idc=useast5; tt-target-idc-sign=hG594kSqj5ODjFKxKHu5O7_f0V5snMn-pNH9xbtYUWPjnSrq6LBUTwNfeMfgVdLAPiOuLNMMg5XQw54qK0h3--UlLvHwwkLKKvtGRPKb0PV3sJSg_M6EAAMDXHVz8dYwteofNu4j7ojwk10lEmZpuzXaAT574unoAu3gk-gJV9DlFkw-kwD_rHOkelP6Lk0Gw1fGDY3Om20-0tVFVJ8mmEOZtjkxnwgZ8-Eo707aT1lGidJ8PZKIbNkgo3udCLpy3rSl-LuUsYiPOfTwg1Ih7nv4Y2OeBOG5w21c9_6Yeo9SGcjf2gtuwQASkjWDy1vLxipf0cYrfFhVlOk2xgZi-RgbhQg62kiYSUe-Mv0zgmYPTTPXMz9okU3Y3IEklz-2adsaZY5kW8qJRBYp1yUhXPr5e7rf04Clj453VxYO5urfI935gMyB8p1KXpJrSaO3OLyZ2YKyNLnEGXBCMBbDzCOrMj8guP42JPOuf-fTIJkYhfHpqqTBHj3h7st22jY3; last_login_method=email; msToken=uhdWmwVzRuGO6X5Qzob8gV2OmXcf6t0FAQeHHIQAx__ZNZubBNAbfK3W7T-E4EN8_OfagmkDu_qAwo6MSaq-qhtPel9tndR7ZaNzoIhsyueXfEYtl8AfTxR9JZk5UemPY7GQ; tt_csrf_token=kOLsNXq3-r4m3r3K1YME0Ga961eYwydSITsM; ak_bmsc=A665D13C6586D765DDF447442952896E~000000000000000000000000000000~YAAQyuIsF15v8sCOAQAAKNIGwhcV5kjZ/zGNalPWSyQXieZLY9SKy2VxEzWDzgy/YRSQLTVBC9WBFE+RXuayfyihX1Rbsm+DQ4sTtTzHIUY20Yu1tWQjcakcvZXtfLp7I0q6fcP9ai53N1iG5wwovNyFJ1eyMQVLm650J2PK59+7DcZn3kmOAHjMl6plVx6mVRoTqXcRte4b5JDtORNbXAbjSgbQiJK5fpJPSFKd19j3C/7hJij3mFvcVMa7hlBIDYlDAshlyrykE/MaoRof0RRZCNuJfO45ZdftS5+YYhuLZXbUsaJXsj3DjmaZj90kNyhovKh4AepeXm6FeC2Mejp4nCILsF0c9nZmTl2jh+TerAffOmdwieV2UejJgfAIcSXrZ1dVWtu0dQ==; passport_fe_beating_status=true; perf_feed_cache={%22expireTimestamp%22:1712822400000%2C%22itemIds%22:[%227351502927267171630%22%2C%227349225060231679275%22%2C%227351880657787800864%22]}; bm_sv=0B6DC970D9D01727EB672641008F9C9D~YAAQxeIsFy0Bw5iOAQAAOChiwhecEatJ7PnT5D7Z1Cr2pcpz/MkHKvKSfCtcnD+888hhDkzPART3agFPgqxJzjotbMOL9vMYCaF331W/Ahjx+/L9pVnvOqKVyhwYw58LJG1NgB2tliqi18Exun04pomLtD195iDMfNbGdYmGt7WrtWumTuI7qEjkR4QAClrPNP1JFYUGT9A29+iGzc+/wqDZiG+0AGXUlTEBmIKM398S9DqSWpJrRvNODjMe7Fg2~1; _waftokenid=eyJ2Ijp7ImEiOiJweEtDTWVrOENLZEZyMDY5bzE1T01KL2RncVNSVWlzZ0xtQVAyZXJDeWw0PSIsImIiOjE3MTI2NTgxMjYsImMiOiJJTU94cGtQS1FuSG1XbVNOYUx0Yk5ldndQR2w5RkxIbkJXaEExOTVPbzFZPSJ9LCJzIjoiL3JDZDl1dXVIWkRvSTc2M1dLM2VHR2hNQU9vbGJGKy9oMFdtTXE3Zkgwaz0ifQ; msToken=J4gOwTXU0OEU6MH3VjhUVmCYMNGqtznsRSDxyl8KNlfSTPM7fMYYXHPPIpldHRFUx_fPfyhVclvrX6WnrNdxk3GzK_7BHmhIIkQbQ1zSSnqY2Phn6QduvErSGvCQyvxwTctWzslT3BqiIg==" # secUid = "MS4wLjABAAAAq1iRXNduFZpY301UkVpJ1eQT60_NiWS9QQSeNqmNQEDJp0pOF8cpleNEdiJx5_IU" # cursor = 0 # count = 30 # coverFormat = 2 # response = await self.fetch_user_collect(cookie, secUid, cursor, count, coverFormat) # print(response) # 获取用户的播放列表 # secUid = "MS4wLjABAAAAtGboV-mJHSIQqh-SsG30QKweGhSqkr4xJLq1qqgAWDzu3vDO5LUhUcCP4UEY5LwC" # cursor = 0 # count = 30 # response = await self.fetch_user_play_list(secUid, cursor, count) # print(response) # 获取用户的合辑列表 # mixId = "7101538765474106158" # cursor = 0 # count = 30 # response = await self.fetch_user_mix(mixId, cursor, count) # print(response) # 获取作品的评论列表 # aweme_id = "7304809083817774382" # cursor = 0 # count = 20 # current_region = "" # response = await self.fetch_post_comment(aweme_id, cursor, count, current_region) # print(response) # 获取作品的评论回复列表 # item_id = "7304809083817774382" # comment_id = "7304877760886588191" # cursor = 0 # count = 20 # current_region = "" # response = await self.fetch_post_comment_reply(item_id, comment_id, cursor, count, current_region) # print(response) # 获取用户的关注列表 # secUid = "MS4wLjABAAAAtGboV-mJHSIQqh-SsG30QKweGhSqkr4xJLq1qqgAWDzu3vDO5LUhUcCP4UEY5LwC" # count = 30 # maxCursor = 0 # minCursor = 0 # response = await self.fetch_user_follow(secUid, count, maxCursor, minCursor) # print(response) # 获取用户的粉丝列表 # secUid = "MS4wLjABAAAAtGboV-mJHSIQqh-SsG30QKweGhSqkr4xJLq1qqgAWDzu3vDO5LUhUcCP4UEY5LwC" # count = 30 # maxCursor = 0 # minCursor = 0 # response = await self.fetch_user_fans(secUid, count, maxCursor, minCursor) # print(response) """-------------------------------------------------------utils接口列表-------------------------------------------------------""" # # 生成真实msToken # response = await self.fetch_real_msToken() # print(response) # 生成ttwid # cookie = "ttwid=1%7Cbf2dxDZQ2bEXkDZCxVuIuo_p3DnLZydqkW-M-yEHrQ8%7C1712664278%7C6ed45f1bb91c86eda1e08c6f60da7898591ed368ee7feece0a78f48d6e734d71; tt_chain_token=AlPMTLvrUZOd3f21B8dbGQ==; tiktok_webapp_theme=light; odin_tt=dada47a81f211d932ae6c5a0dc99b4e87029d27b49b0fc4a83faf6bc91bebddcf3665c25f1a7c0934dc27c89ab2a7151e116cc22110c24b927051de11b54c3e66e6567dba55e88d2f92f52a7b857d27f; passport_csrf_token=fd79484bbdda182d711ad15fa11c059d; passport_csrf_token_default=fd79484bbdda182d711ad15fa11c059d; multi_sids=7262344915936658478%3Aa5b1dc5805dee79797d4470ffa822e45; cmpl_token=AgQQAPNSF-RO0rT35p6-9h0X_5yvjXFav6jZYNCqgQ; sid_guard=a5b1dc5805dee79797d4470ffa822e45%7C1711264624%7C15552000%7CFri%2C+20-Sep-2024+07%3A17%3A04+GMT; uid_tt=59c2975ea05dc11e9f7f548a658d65348935cb555d188c432fe2e5d0bd6b75e1; uid_tt_ss=59c2975ea05dc11e9f7f548a658d65348935cb555d188c432fe2e5d0bd6b75e1; sid_tt=a5b1dc5805dee79797d4470ffa822e45; sessionid=a5b1dc5805dee79797d4470ffa822e45; sessionid_ss=a5b1dc5805dee79797d4470ffa822e45; sid_ucp_v1=1.0.0-KDNkZDkzMWRkNzMwOTU4NWVjZWNjZDAxZGE0NDgyNDJlYWQ3MTU4YjcKIAiuiJO2k4fC5GQQ8Kb_rwYYswsgDDDCkaSmBjgBQOoHEAQaB3VzZWFzdDUiIGE1YjFkYzU4MDVkZWU3OTc5N2Q0NDcwZmZhODIyZTQ1; ssid_ucp_v1=1.0.0-KDNkZDkzMWRkNzMwOTU4NWVjZWNjZDAxZGE0NDgyNDJlYWQ3MTU4YjcKIAiuiJO2k4fC5GQQ8Kb_rwYYswsgDDDCkaSmBjgBQOoHEAQaB3VzZWFzdDUiIGE1YjFkYzU4MDVkZWU3OTc5N2Q0NDcwZmZhODIyZTQ1; store-idc=useast5; store-country-code=us; store-country-code-src=uid; tt-target-idc=useast5; tt-target-idc-sign=hG594kSqj5ODjFKxKHu5O7_f0V5snMn-pNH9xbtYUWPjnSrq6LBUTwNfeMfgVdLAPiOuLNMMg5XQw54qK0h3--UlLvHwwkLKKvtGRPKb0PV3sJSg_M6EAAMDXHVz8dYwteofNu4j7ojwk10lEmZpuzXaAT574unoAu3gk-gJV9DlFkw-kwD_rHOkelP6Lk0Gw1fGDY3Om20-0tVFVJ8mmEOZtjkxnwgZ8-Eo707aT1lGidJ8PZKIbNkgo3udCLpy3rSl-LuUsYiPOfTwg1Ih7nv4Y2OeBOG5w21c9_6Yeo9SGcjf2gtuwQASkjWDy1vLxipf0cYrfFhVlOk2xgZi-RgbhQg62kiYSUe-Mv0zgmYPTTPXMz9okU3Y3IEklz-2adsaZY5kW8qJRBYp1yUhXPr5e7rf04Clj453VxYO5urfI935gMyB8p1KXpJrSaO3OLyZ2YKyNLnEGXBCMBbDzCOrMj8guP42JPOuf-fTIJkYhfHpqqTBHj3h7st22jY3; last_login_method=email; msToken=t3WAFkKaIqii9eMTPHdks49bnQnrcb-qA8i0K6CbTF-2MBdObKnGfU3icz53Wot781BQXPL4PT4ZI2nIFacyECthXfFPg6JrkghC_Yn7pf6aut5YU7PpqeuAa3Ipg-1OAYS2rF3UrQOetw==; tt_csrf_token=kOLsNXq3-r4m3r3K1YME0Ga961eYwydSITsM; passport_fe_beating_status=true; ak_bmsc=24B67BCA11EE8356DD40E4F7E23FC910~000000000000000000000000000000~YAAQyOIsF//Uz6COAQAAe/5/whdqkLc0AH5d8i2rlJjtjjMuK1K+tU3kWANu/7PWSoOfbjdVZi9uFRKsuQj1DU0Ztew9uihAT+jWEvqNo1cbee/FRwJLMZk80po2nI/GwpLKd51dHN5HW7dWc58oeWwpIOh/g2uVkXJjtVotM4sBcEYxO1i9fpOF0bgOOVXrElmpqaFVfWBJc0iBBHHBZEAHNSIGHjPHY7j+Gy4YMoldkJKJbMVtRWa3ChfagC7vgWsiy2sb3lDGRbSQgjYj128i2lwoPtbcA3bzLZPd6jseTgRHm01arjyMJh3RrhDUyu71D1jMPuWhVkAjAV21vrsJFmgFWQ3Ryv23yDa6kSq7qRBLQAxA6rYcYBRNPdoNOAaiLt5IBCHiWQ==; bm_sv=FB0D8C84058596C33C95C34477181900~YAAQ3+IsF1bJy52OAQAAIOy+whed7uxWbcSbX9ww9mH0hyPTbQLecKO8qrRli6xSOco/iX7wxO9RXW6ikifIc2RFIbvzAZg3j58QNuEJ5hXrIia0yc0T/j1cCjhqBypDWXc6KaC716f293K5lbOFoD7QMFCA3K4YsMK3mJa2KaBzOvwOTdbpmow8PM0fKAXwSxJDPweGCzxZhiMNC+H/TFscBYb5HdDZ7PkuiN97YPtVEtfMd4WcpHos3e5dFJS+~1; living_user_id=743289106087; csrfToken=ndffXer7-a5_J5Me7ffRmSSJfzfMDmX3B6oM; perf_feed_cache={%22expireTimestamp%22:1712836800000%2C%22itemIds%22:[%227348432053190380842%22%2C%227352682225256762666%22%2C%227350485674086157611%22]}; csrf_session_id=120d8aacffb06addd01cb40859003c8e; msToken=8tbUEEpe8rNjEkOrH6M5v-RXjSUaCAARr-Knyk11POdQHvjVvQjbXEbEP4vcAf2ftbB7ycHOz7LlQbADkPURuVvseAstrFbSmxY3uVJOLAgS6O9h3BnXmpHH_kPw4xXgF2zDv4E-U58JZw==" # response = await self.gen_ttwid(cookie) # print(response) # 生成xbogus # url = "https://www.tiktok.com/api/item/detail/?WebIdLastTime=1712665533&aid=1988&app_language=en&app_name=tiktok_web&browser_language=en-US&browser_name=Mozilla&browser_online=true&browser_platform=Win32&browser_version=5.0%20%28Windows%29&channel=tiktok_web&cookie_enabled=true&device_id=7349090360347690538&device_platform=web_pc&focus_state=true&from_page=user&history_len=4&is_fullscreen=false&is_page_visible=true&language=en&os=windows&priority_region=US&referer=®ion=US&root_referer=https%3A%2F%2Fwww.tiktok.com%2F&screen_height=1080&screen_width=1920&webcast_language=en&tz_name=America%2FTijuana&msToken=AYFCEapCLbMrS8uTLBoYdUMeeVLbCdFQ_QF_-OcjzJw1CPr4JQhWUtagy0k4a9IITAqi5Qxr2Vdh9mgCbyGxTnvWLa4ZVY6IiSf6lcST-tr0IXfl-r_ZTpzvWDoQfqOVsWCTlSNkhAwB-tap5g==&itemId=7339393672959757570" # user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3" # response = await self.gen_xbogus(url, user_agent) # print(response) # 提取单个用户secUid # url = "https://www.tiktok.com/@tiktok" # response = await self.get_sec_user_id(url) # print(response) # 提取多个用户secUid # urls = ["https://www.tiktok.com/@tiktok", "https://www.tiktok.com/@taylorswift"] # response = await self.get_all_sec_user_id(urls) # print(response) # 提取单个作品id # url = "https://www.tiktok.com/@taylorswift/video/7162153915952352558" # response = await self.get_aweme_id(url) # print(response) # 提取多个作品id # urls = ["https://www.tiktok.com/@taylorswift/video/7162153915952352558", "https://www.tiktok.com/@taylorswift/video/7137077445680745771"] # response = await self.get_all_aweme_id(urls) # print(response) # 获取用户unique_id # url = "https://www.tiktok.com/@tiktok" # response = await self.get_unique_id(url) # print(response) # 获取多个用户unique_id # urls = ["https://www.tiktok.com/@tiktok", "https://www.tiktok.com/@taylorswift"] # response = await self.get_all_unique_id(urls) # print(response) # 占位 pass if __name__ == "__main__": # 初始化 TikTokWebCrawler = TikTokWebCrawler() # 开始时间 start = time.time() asyncio.run(TikTokWebCrawler.main()) # 结束时间 end = time.time() print(f"耗时:{end - start}")