Skip to content

Commit

Permalink
Merge pull request #382 from davidteather/nightly
Browse files Browse the repository at this point in the history
V3.8.0 Fix Trending & UserPosts & Better Exception Handling & Dockerfile
  • Loading branch information
davidteather authored Nov 21, 2020
2 parents a385538 + 4339ffa commit 1fbb5b2
Show file tree
Hide file tree
Showing 19 changed files with 379 additions and 196 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ res.html
tmp/*
dist/*
*.egg-info
tmp/
tmp
.pytest_cache/*
test.mp4
test.txt
Expand Down
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM mcr.microsoft.com/playwright:focal

RUN apt-get update && apt-get install -y python3-pip
COPY . .
RUN pip3 install TikTokApi
30 changes: 21 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ python -m playwright install

If you're on MacOS you may need to install [XCode Developer Tools](https://webkit.org/build-tools/)

#### Docker Installation

Clone this repository onto a local machine then run the following commands.

```
docker build . -t tiktokapi:latest
docker run -v TikTokApi --rm tiktokapi:latest python3 your_script.py
```

**Note** this assumes your script is named your_script.py and lives in the root of this directory.

### Common Issues

Expand All @@ -86,7 +96,9 @@ api = TikTokApi.get_instance()
results = 10
trending = api.trending(count=results)
# Since TikTok changed their API you need to use the custom_verifyFp option.
# In your web browser you will need to go to TikTok, Log in and get the s_v_web_id value.
trending = api.trending(count=results, custom_verifyFp="")
for tiktok in trending:
# Prints the id of the tiktok
Expand Down Expand Up @@ -133,7 +145,7 @@ executablePath - The path to your chromedriver if you don't want global install
##### The trending Method

```
api.trending(self, count=30, referrer="https://www.tiktok.com/@ondymikula/video/6756762109670477061", language='en', proxy=None)
api.trending(self, count=30, referrer="https://www.tiktok.com/@ondymikula/video/6756762109670477061", language='en', proxy=None, , custom_verifyFp="")
```

count - this is how many trending Tiktoks you want to be returned.
Expand All @@ -143,7 +155,7 @@ Trending returns an array of dictionaries. Example structure [here](https://www.
##### The get_Video_By_TikTok Method

```
api.get_Video_By_TikTok(data, language='en', proxy=None)
api.get_Video_By_TikTok(data, language='en', proxy=None, , custom_verifyFp="")
```

data - The tiktok dictionary returned from the API. Will return bytes.
Expand Down Expand Up @@ -302,7 +314,7 @@ getSuggestedMusicIDCrawler(self, count=30, startingId='6745191554350760966', lan
##### The get_Video_By_DownloadURL Method

```
api.get_Video_By_DownloadURL(url, language='en', proxy=None)
api.get_Video_By_DownloadURL(url, language='en', proxy=None, custom_verifyFp="")
```

url - The download url that's found in the TikTok dictionary. TikTok['video']['downloadAddr']
Expand All @@ -311,7 +323,7 @@ url - The download url that's found in the TikTok dictionary. TikTok['video']['d
##### The get_Video_By_Url Method

```
api.get_Video_By_Url(video_url, return_bytes=0)
api.get_Video_By_Url(video_url, return_bytes=0, custom_verifyFp="")
```

video_url - The video you want to get url.
Expand All @@ -321,7 +333,7 @@ return_bytes - The default value is 0, when it is set to 1 the function instead
##### The get_Video_No_Watermark_Faster Method

```
api.get_Video_No_Watermark(video_url, return_bytes=0, language='en', proxy=None)
api.get_Video_No_Watermark(video_url, return_bytes=0, language='en', proxy=None, custom_verifyFp="")
```

video_url - The video you want to get url.
Expand All @@ -330,7 +342,7 @@ return_bytes - The default value is 0, when it is set to 1 the function instead

If you request without bytes you will need to make a call to the URL it responds yourself to get bytes.
```
url = api.get_Video_No_Watermark_ID('6829267836783971589', return_bytes=0)
url = api.get_Video_No_Watermark_ID('6829267836783971589', return_bytes=0, custom_verifyFp="")
import requests
video_bytes = requests.get(url, headers={"User-Agent": "okhttp"}).content
Expand Down Expand Up @@ -371,7 +383,7 @@ You can use this method if you really want, but just use the 3 above it.
##### The get_Video_No_Watermark_ID Method

```
api.get_Video_No_Watermark_ID(self, video_id, return_bytes=1, proxy=None)
api.get_Video_No_Watermark_ID(self, video_id, return_bytes=1, proxy=None, custom_verifyFp="")
```

video_id - The video id you want to get.
Expand All @@ -389,7 +401,7 @@ video_bytes = requests.get(url, headers={"User-Agent": "okhttp"}).content

##### The get_Video_No_Watermark Method
```
api.get_Video_No_Watermark(self, video_url, return_bytes=0, proxy=None)
api.get_Video_No_Watermark(self, video_url, return_bytes=0, proxy=None, custom_verifyFp="")
```

This endpoint returns a url that is able to be opened in any browser, but sacrifices speed for this convenience. Any old request library can return the bytes if you decide to return a url.
Expand Down
57 changes: 33 additions & 24 deletions TikTokApi/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import requests
import logging
from threading import Thread
import time, datetime
import time
import datetime
import random


Expand All @@ -15,14 +16,15 @@

playwright = None


def get_playwright():
global playwright
if playwright == None:
if playwright is None:
try:
playwright = sync_playwright().start()
except Exception as e:
raise e

return playwright


Expand Down Expand Up @@ -55,7 +57,7 @@ def __init__(
"handleSIGHUP": True,
}

if self.proxy != None:
if self.proxy is not None:
if "@" in self.proxy:
server_prefix = self.proxy.split("://")[0]
address = self.proxy.split("@")[1]
Expand All @@ -69,11 +71,13 @@ def __init__(

self.options.update(options)

if self.executablePath != None:
if self.executablePath is not None:
self.options["executablePath"] = self.executablePath

try:
self.browser = get_playwright().webkit.launch(args=self.args, **self.options)
self.browser = get_playwright().webkit.launch(
args=self.args, **self.options
)
except Exception as e:
raise e
logging.critical(e)
Expand All @@ -83,9 +87,11 @@ def __init__(
page.close()

def get_params(self, page) -> None:
# self.browser_language = await self.page.evaluate("""() => { return navigator.language || navigator.userLanguage; }""")
# 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 = 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 = ""
Expand Down Expand Up @@ -114,13 +120,13 @@ def create_page(self, set_useragent=False):

return page

def base36encode(self, number, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
def base36encode(self, number, alphabet="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
"""Converts an integer to a base36 string."""
base36 = ''
sign = ''
base36 = ""
sign = ""

if number < 0:
sign = '-'
sign = "-"
number = -number

if 0 <= number < len(alphabet):
Expand All @@ -138,15 +144,15 @@ def gen_verifyFp(self):
chars_len = len(chars)
scenarioTitle = self.base36encode(int(time.time() * 1000))
uuid = [0] * 36
uuid[8] = '_'
uuid[13] = '_'
uuid[18] = '_'
uuid[23] = '_'
uuid[8] = "_"
uuid[13] = "_"
uuid[18] = "_"
uuid[23] = "_"
uuid[14] = "4"
r = None
for i in range(36):
if uuid[i] == 0:
if r == None:
if r is None:
r = 0
else:
r = random.random() * chars_len
Expand All @@ -155,9 +161,10 @@ def gen_verifyFp(self):
for x in uuid:
ending += str(x)
return "verify_" + scenarioTitle + "_" + ending

def sign_url(self, **kwargs):
url = kwargs.get("url", None)
if url == None:
if url is None:
raise Exception("sign_url required a url parameter")
page = self.create_page()
verifyFp = "".join(
Expand All @@ -170,12 +177,14 @@ def sign_url(self, **kwargs):
if kwargs.get("gen_new_verifyFp", False):
verifyFp = self.gen_verifyFp()
else:
verifyFp = kwargs.get("custom_verifyFp", "verify_khgp4f49_V12d4mRX_MdCO_4Wzt_Ar0k_z4RCQC9pUDpX")

verifyFp = kwargs.get(
"custom_verifyFp",
"verify_khgp4f49_V12d4mRX_MdCO_4Wzt_Ar0k_z4RCQC9pUDpX",
)

if kwargs.get("custom_did", None) != None:
if kwargs.get("custom_did") is not None:
did = kwargs.get("custom_did", None)
elif self.did == None:
elif self.did is None:
did = str(random.randint(10000, 999999999))
else:
did = self.did
Expand Down Expand Up @@ -203,7 +212,7 @@ def sign_url(self, **kwargs):
def clean_up(self):
try:
self.browser.close()
except:
except Exception:
logging.info("cleanup failed")
# playwright.stop()

Expand All @@ -212,7 +221,7 @@ def find_redirect(self, url):
self.redirect_url = self.page.url

def __format_proxy(self, proxy):
if proxy != None:
if proxy is not None:
return {"http": proxy, "https": proxy}
else:
return None
Expand Down
25 changes: 25 additions & 0 deletions TikTokApi/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class TikTokCaptchaError(Exception):
def __init__(
self,
message="TikTok blocks this request displaying a Captcha \nTip: Consider using a proxy or a custom_verifyFp as method parameters",
):
self.message = message
super().__init__(self.message)


class TikTokNotFoundError(Exception):
def __init__(self, message="The requested object does not exists"):
self.message = message
super().__init__(self.message)


class EmptyResponseError(Exception):
def __init__(self, message="TikTok sent no data back"):
self.message = message
super().__init__(self.message)


class JSONDecodeFailure(Exception):
def __init__(self, message="TikTok sent invalid JSON back"):
self.message = message
super().__init__(self.message)
Loading

0 comments on commit 1fbb5b2

Please sign in to comment.