diff --git a/TikTokApi/tiktok.py b/TikTokApi/tiktok.py index a9e0ded3..7b133f8e 100644 --- a/TikTokApi/tiktok.py +++ b/TikTokApi/tiktok.py @@ -2,6 +2,7 @@ import requests import time import logging +import json from urllib.parse import urlencode, quote from .browser import browser, get_playwright from playwright import sync_playwright @@ -154,7 +155,7 @@ def getData(self, **kwargs) -> dict: "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "user-agent": userAgent, - "cookie": "tt_webid_v2=" + did, + "cookie": "tt_webid_v2=" + did + ';s_v_web_id=' + kwargs.get("custom_verifyFp", "verify_khgp4f49_V12d4mRX_MdCO_4Wzt_Ar0k_z4RCQC9pUDpX"), }, proxies=self.__format_proxy(proxy), ) @@ -685,6 +686,16 @@ def bySound(self, id, count=30, offset=0, **kwargs) -> dict: def getMusicObject(self, id, **kwargs) -> dict: """Returns a music object for a specific sound id. + :param id: The sound id to search by. + :param language: The 2 letter code of the language to return. + Note: Doesn't seem to have an affect. + :param proxy: The IP address of a proxy to make requests from. + """ + return self.getMusicObjectFull(id, **kwargs)['music'] + + def getMusicObjectFull(self, id, **kwargs): + """Returns a music object for a specific sound id. + :param id: The sound id to search by. :param language: The 2 letter code of the language to return. Note: Doesn't seem to have an affect. @@ -697,14 +708,18 @@ def getMusicObject(self, id, **kwargs) -> dict: maxCount, did, ) = self.__process_kwargs__(kwargs) - kwargs['custom_did'] = did - - query = {"musicId": id, "language": language} - api_url = "{}node/share/music/{}?{}&{}".format( - BASE_URL, self.get_music_title(id, **kwargs) + "-" + str(id), self.__add_new_params__(), urlencode(query) - ) - - return self.getData(url=api_url, **kwargs) + r = requests.get("https://www.tiktok.com/music/-{}".format(id), headers={ + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "authority": "www.tiktok.com", + "Accept-Encoding": "gzip, deflate", + "Connection": "keep-alive", + "Host": "www.tiktok.com", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36", + "Cookie": "s_v_web_id=" + kwargs.get("custom_verifyFp", "verify_khgp4f49_V12d4mRX_MdCO_4Wzt_Ar0k_z4RCQC9pUDpX"), + }, proxies=self.__format_proxy(kwargs.get("proxy", None))) + t = r.text + j_raw = t.split('")[0] + return json.loads(j_raw)['props']['pageProps']['musicInfo'] def byHashtag(self, hashtag, count=30, offset=0, **kwargs) -> dict: """Returns a dictionary listing TikToks with a specific hashtag. @@ -999,14 +1014,22 @@ def getUser(self, username, **kwargs) -> dict: maxCount, did, ) = self.__process_kwargs__(kwargs) - kwargs['custom_did'] = did - secUid = self.get_secUid(username) - query = {"uniqueId": username, "language": language, "isUniqueId": True, "validUniqueId": username, "sec_uid": "", "secUid": secUid} - api_url = "{}node/share/user/@{}?{}&{}".format( - BASE_URL, quote(username), self.__add_new_params__(), urlencode(query) - ) + r = requests.get("https://tiktok.com/@{}?lang=en".format(username), headers={ + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "authority": "www.tiktok.com", + "path": "/{}".format(username), + "Accept-Encoding": "gzip, deflate", + "Connection": "keep-alive", + "Host": "www.tiktok.com", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36", + "Cookie": "s_v_web_id=" + kwargs.get("custom_verifyFp", "verify_khgp4f49_V12d4mRX_MdCO_4Wzt_Ar0k_z4RCQC9pUDpX"), + }, proxies=self.__format_proxy(kwargs.get("proxy", None))) - return self.getData(url=api_url, **kwargs) + t = r.text + + j_raw = t.split('")[0] + + return json.loads(j_raw)['props']['pageProps'] def getSuggestedUsersbyID( self, userId="6745191554350760966", count=30, **kwargs @@ -1334,14 +1357,24 @@ def get_Video_No_Watermark(self, video_url, return_bytes=0, **kwargs) -> bytes: return r.content def get_music_title(self, id, **kwargs): - r = requests.get("https://www.tiktok.com/music/-{}".format(id), proxies=self.__format_proxy(kwargs.get("proxy", None))) - text = r.text.split('TikTok","desc":')[0] - on_tiktok = text.split(" | ") - return on_tiktok[len(on_tiktok)-2].split(" ")[1] + r = requests.get("https://www.tiktok.com/music/-{}".format(id), headers={ + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "authority": "www.tiktok.com", + "Accept-Encoding": "gzip, deflate", + "Connection": "keep-alive", + "Host": "www.tiktok.com", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36", + "Cookie": "s_v_web_id=" + kwargs.get("custom_verifyFp", "verify_khgp4f49_V12d4mRX_MdCO_4Wzt_Ar0k_z4RCQC9pUDpX"), + }, proxies=self.__format_proxy(kwargs.get("proxy", None))) + t = r.text + j_raw = t.split('")[0] + return json.loads(j_raw)['props']['pageProps']['musicInfo']['title'] def get_secUid(self, username, **kwargs): r = requests.get("https://tiktok.com/@{}?lang=en".format(username), headers={ - "Accept": "*/*", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "authority": "www.tiktok.com", + "path": "/{}".format(username), "Accept-Encoding": "gzip, deflate", "Connection": "keep-alive", "Host": "www.tiktok.com", diff --git a/setup.py b/setup.py index 9925d388..a857e4cf 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setuptools.setup( name="TikTokApi", packages=["TikTokApi"], - version="3.7.8", + version="3.7.9", license="MIT", description="The Unofficial TikTok API Wrapper in Python 3.", author="David Teather",