Skip to content

Commit

Permalink
V4.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
davidteather committed Sep 22, 2021
1 parent 1cb0c8b commit 80ecfa1
Show file tree
Hide file tree
Showing 18 changed files with 1,333 additions and 249 deletions.
1 change: 1 addition & 0 deletions TikTokApi/browser_utilities/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .browser_interface import BrowserInterface
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
import string
import requests
import logging
from threading import Thread
import time
import datetime
import random
import json
import re
from .browser_interface import BrowserInterface
from urllib.parse import splitquery, parse_qs, parse_qsl


# Import Detection From Stealth
from .stealth import stealth
from .get_acrawler import get_acrawler, get_tt_params_script
from playwright.sync_api import sync_playwright

Expand All @@ -31,7 +29,7 @@ def get_playwright():
return playwright


class browser:
class browser(BrowserInterface):
def __init__(
self,
**kwargs,
Expand All @@ -44,7 +42,6 @@ def __init__(
self.language = kwargs.get("language", "en")
self.executablePath = kwargs.get("executablePath", None)
self.device_id = kwargs.get("custom_device_id", None)
find_redirect = kwargs.get("find_redirect", False)

args = kwargs.get("browser_args", [])
options = kwargs.get("browser_options", {})
Expand Down Expand Up @@ -83,8 +80,8 @@ def __init__(
args=self.args, **self.options
)
except Exception as e:
raise e
logging.critical(e)
raise e

context = self.create_context(set_useragent=True)
page = context.new_page()
Expand Down
18 changes: 18 additions & 0 deletions TikTokApi/browser_utilities/browser_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import abc
class BrowserInterface(abc.ABC):
@abc.abstractmethod
def __init__(self, **kwargs):
pass

@abc.abstractmethod
def get_params(self, page) -> None:
pass

# Returns verify_fp, device_id, signature, tt_params
@abc.abstractmethod
def sign_url(self, calc_tt_params=False, **kwargs) -> tuple[str, str, str, str]:
pass

@abc.abstractmethod
def clean_up(self) -> None:
pass
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import random
import time
import string
import requests
import logging
from threading import Thread
import time
import datetime
import re
import random
import json
from .browser_interface import BrowserInterface
from selenium_stealth import stealth
from selenium import webdriver
from .get_acrawler import get_acrawler
from .get_acrawler import get_acrawler, get_tt_params_script
from urllib.parse import splitquery, parse_qs, parse_qsl


class browser:
class browser(BrowserInterface):
def __init__(
self,
**kwargs,
):
self.kwargs = kwargs
self.debug = kwargs.get("debug", False)
self.proxy = kwargs.get("proxy", None)
self.api_url = kwargs.get("api_url", None)
Expand Down Expand Up @@ -81,26 +83,32 @@ def setup_browser(self):
renderer="Intel Iris OpenGL Engine",
fix_hairline=True,
)

self.get_params(self.browser)
# NOTE: Slower than playwright at loading this because playwright can ignore unneeded files.
self.browser.get("https://www.tiktok.com/@redbull")
self.browser.execute_script(get_acrawler())
self.browser.execute_script(get_tt_params_script())


def get_params(self, page) -> None:
# self.browser_language = await self.page.evaluate("""() => { return
# navigator.language || navigator.userLanguage; }""")
self.browser_language = ""
# self.timezone_name = await self.page.evaluate("""() => { return
# Intl.DateTimeFormat().resolvedOptions().timeZone; }""")
self.timezone_name = ""
# self.browser_platform = await self.page.evaluate("""() => { return window.navigator.platform; }""")
self.browser_platform = ""
# self.browser_name = await self.page.evaluate("""() => { return window.navigator.appCodeName; }""")
self.browser_name = ""
# self.browser_version = await self.page.evaluate("""() => { return window.navigator.appVersion; }""")
self.browser_version = ""

self.width = page.execute_script("""return screen.width""")
self.height = page.execute_script("""return screen.height""")
self.userAgent = page.execute_script("""return navigator.userAgent""")
self.browser_language = self.kwargs.get("browser_language", ("""return navigator.language"""))
self.browser_version = ("""return window.navigator.appVersion""")

if len(self.browser_language.split("-")) == 0:
self.region = self.kwargs.get("region", "US")
self.language = self.kwargs.get("language", "en")
elif len(self.browser_language.split("-")) == 1:
self.region = self.kwargs.get("region", "US")
self.language = self.browser_language.split("-")[0]
else:
self.region = self.kwargs.get("region", self.browser_language.split("-")[1])
self.language = self.kwargs.get("language", self.browser_language.split("-")[0])

self.timezone_name = self.kwargs.get("timezone_name", ("""return Intl.DateTimeFormat().resolvedOptions().timeZone"""))
self.width = ("""return screen.width""")
self.height = ("""return screen.height""")

def base36encode(self, number, alphabet="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
"""Converts an integer to a base36 string."""
Expand Down Expand Up @@ -139,11 +147,12 @@ def gen_verifyFp(self):

return f'verify_{scenario_title.lower()}_{"".join(uuid)}'

def sign_url(self, **kwargs):
def sign_url(self, calc_tt_params=False, **kwargs):
url = kwargs.get("url", None)
if url is None:
raise Exception("sign_url required a url parameter")

tt_params = None
if kwargs.get("gen_new_verifyFp", False):
verifyFp = self.gen_verifyFp()
else:
Expand All @@ -159,24 +168,37 @@ def sign_url(self, **kwargs):
else:
device_id = self.device_id

return (
verifyFp,
device_id,
url = '{}&verifyFp={}&device_id={}'.format(url, verifyFp, device_id)
# self.browser.execute_script(content=get_acrawler())
# Should be covered by an earlier addition of get_acrawler.
evaluatedPage = (
self.browser.execute_script(
'''
var url = "'''
+ url
+ "&verifyFp="
+ verifyFp
+ """&device_id="""
+ device_id
+ """"
var url = "'''+ url + """"
var token = window.byted_acrawler.sign({url: url});
return token;
"""
),
)

url = '{}&_signature={}'.format(url, evaluatedPage)
# self.browser.execute_script(content=get_tt_params_script())
# Should be covered by an earlier addition of get_acrawler.

tt_params = self.browser.execute_script(
'''() => {
return window.genXTTParams(''' + json.dumps(dict(parse_qsl(splitquery(url)[1]))) + ''');
}'''
)

return (
verifyFp,
device_id,
evaluatedPage,
tt_params
)

def clean_up(self):
try:
self.browser.close()
Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions TikTokApi/tiktok.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ def __init__(self, **kwargs):
global BASE_URL
BASE_URL = "https://t.tiktok.com/"
if kwargs.get("use_selenium", False):
from .browser_selenium import browser
from .browser_utilities.browser_selenium import browser
else:
from .browser import browser
from .browser_utilities.browser import browser

if kwargs.get("generate_static_device_id", False):
self.custom_device_id = "".join(random.choice(string.digits) for num in range(19))
Expand Down
9 changes: 3 additions & 6 deletions docs/TikTokApi.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ <h2>Contents</h2>
<ul>
<li><a href="#unofficial-tiktok-api-in-python">Unofficial TikTok API in Python</a>
<ul>
<li><a href="#thank-you-to-our-sponsors-advertisers">Thank you to our sponsors &amp; advertisers</a></li>
<li><a href="#sponsors-tiktokapi-is-free">Sponsors (TikTokApi is free)</a></li>
<li><a href="#table-of-contents">Table of Contents</a></li>
<li><a href="#getting-started">Getting Started</a>
<ul>
Expand All @@ -53,11 +53,8 @@ <h2>Contents</h2>

<h2>Submodules</h2>
<ul>
<li><a href="TikTokApi/browser.html">TikTokApi.browser</a></li>
<li><a href="TikTokApi/browser_selenium.html">TikTokApi.browser_selenium</a></li>
<li><a href="TikTokApi/browser_utilities.html">TikTokApi.browser_utilities</a></li>
<li><a href="TikTokApi/exceptions.html">TikTokApi.exceptions</a></li>
<li><a href="TikTokApi/get_acrawler.html">TikTokApi.get_acrawler</a></li>
<li><a href="TikTokApi/stealth.html">TikTokApi.stealth</a></li>
<li><a href="TikTokApi/tiktok.html">TikTokApi.tiktok</a></li>
<li><a href="TikTokApi/tiktokuser.html">TikTokApi.tiktokuser</a></li>
<li><a href="TikTokApi/utilities.html">TikTokApi.utilities</a></li>
Expand All @@ -82,7 +79,7 @@ <h1 class="modulename">

<p><a href="https://www.linkedin.com/in/davidteather/"><img src="https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&amp;logo=linkedin&amp;logoColor=white&amp;style=flat-square" alt="LinkedIn" /></a> <a href="https://github.com/sponsors/davidteather"><img src="https://img.shields.io/static/v1?label=Sponsor&amp;message=%E2%9D%A4&amp;logo=GitHub" alt="Sponsor Me" /></a> <a href="https://github.com/davidteather/TikTok-Api/releases"><img src="https://img.shields.io/github/v/release/davidteather/TikTok-Api" alt="GitHub release (latest by date)" /></a> <a href="https://github.com/davidteather/TikTok-Api/actions/workflows/package-test.yml"><img src="https://img.shields.io/github/workflow/status/davidteather/tiktok-api/TikTokApi%20CI/master" alt="Build Status" /></a> <a href="https://github.com/davidteather/TikTok-Api/blob/master/LICENSE"><img src="https://img.shields.io/github/license/davidteather/TikTok-Api" alt="GitHub" /></a> <a href="https://pypi.org/project/TikTokApi/"><img src="https://pepy.tech/badge/tiktokapi" alt="Downloads" /></a> <img src="https://visitor-badge.laobi.icu/badge?page_id=davidteather.TikTok-Api" alt="" /> <a href="https://discord.gg/yyPhbfma6f"><img src="https://img.shields.io/discord/783108952111579166.svg?color=7289da&amp;logo=discord&amp;style=flat-square" alt="Support Server" /></a></p>

<h2 id="thank-you-to-our-sponsors-advertisers">Thank you to our sponsors &amp; advertisers</h2>
<h2 id="sponsors-tiktokapi-is-free">Sponsors (TikTokApi is free)</h2>

<p><a href="https://tikapi.io/?ref=davidteather"><img src="imgs/logo128.png" alt="TikAPI" /></a> | <strong><a href="https://tikapi.io/?ref=davidteather">TikAPI</a></strong> is a paid TikTok API service providing an full out-of-the-box solution for developers, trusted by 100+ companies. <a href="https://tikapi.io/?ref=davidteather">Learn more</a>
:-------------------------:|:-------------------------:</p>
Expand Down
Loading

0 comments on commit 80ecfa1

Please sign in to comment.