Skip to content

Commit 186c9a1

Browse files
committed
Fix SDK
1 parent bdebe62 commit 186c9a1

File tree

12 files changed

+815
-412
lines changed

12 files changed

+815
-412
lines changed

README.en.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
<p>调用这些接口会使用你账户中的剩余请求次数!</p>
1313

1414
```python
15-
from tikhub.api import *
15+
from tikhub.__main__ import *
1616

1717
# 初始化(Initialization)
1818
api = API(
19-
email='EMAIL@EXAMPLE.COM',
20-
password='PASSWORD',
21-
proxy=None,
19+
email='EMAIL@EXAMPLE.COM',
20+
password='PASSWORD',
21+
proxy=None,
2222
)
2323
```
2424

@@ -51,7 +51,7 @@ pip install tikhub
5151
- Usage
5252

5353
```python
54-
from tikhub.api import *
54+
from tikhub.__main__ import *
5555

5656

5757
async def async_test() -> None:

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
<p>调用这些接口会使用你账户中的剩余请求次数!</p>
1313

1414
```python
15-
from tikhub.api import *
15+
from tikhub.__main__ import *
1616

1717
# 初始化(Initialization)
1818
api = API(
19-
email='EMAIL@EXAMPLE.COM',
20-
password='PASSWORD',
21-
proxy=None,
19+
email='EMAIL@EXAMPLE.COM',
20+
password='PASSWORD',
21+
proxy=None,
2222
)
2323
```
2424

@@ -51,7 +51,7 @@ pip install tikhub
5151
- Usage
5252

5353
```python
54-
from tikhub.api import *
54+
from tikhub.__main__ import *
5555

5656

5757
async def async_test() -> None:

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
setuptools.setup(
1515
name='tikhub',
1616
author='TikHub.io',
17-
version='1.0.2',
17+
version='1.0.3',
1818
license='Apache V2.0 License',
19-
description='Douyin/TikTok async data scraper.',
19+
description='TikHub Unofficial 抖音/TikTok/小红书 RESTful API',
2020
long_description=long_description,
2121
long_description_content_type="text/markdown",
2222
author_email='tikhub.io@proton.me',
2323
url='https://github.com/orgs/TikHubIO',
2424
packages=setuptools.find_packages(),
25-
keywords='TikTok, Douyin, 抖音, Scraper, Crawler, API, Download, Video, No Watermark, Async',
25+
keywords='TikTok, Douyin, 抖音, 小红书, Scraper, Crawler, API, Download, Video, No Watermark, Async',
2626
# 依赖包
2727
install_requires=[
2828
'aiohttp',

test/test.py

Lines changed: 32 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,49 @@
1-
from tikhub.api import *
1+
import asyncio
22

3+
from tikhub import TikTokAPI, DouyinAPI
34

4-
async def async_test() -> None:
5-
# 异步测试/Async test
65

7-
tiktok_url = 'https://www.tiktok.com/@evil0ctal/video/7156033831819037994'
8-
9-
tiktok_music_url = 'https://www.tiktok.com/music/original-sound-7128362040359488261'
10-
11-
douyin_url = 'https://www.douyin.com/video/7153585499477757192'
6+
if __name__ == '__main__':
7+
token = input('Please enter your TikTok token: ')
128

13-
douyin_user_url = 'https://www.douyin.com/user/MS4wLjABAAAAaNJuvXC83kL5nhaZHubKdjsRJQovgz58wXzlLnJUsslG-Kb24TM1QJlf_2HMaUJk'
9+
tiktok_api = TikTokAPI(token)
10+
douyin_api = DouyinAPI(token)
1411

15-
print("Test start...\n")
16-
start_time = time.time()
12+
tiktok_video_url = "https://www.tiktok.com/@evil0ctal/video/7201344014984006954"
1713

18-
# 获取TikHub请求头/Get TikHub request header
19-
r = await api.user_login()
20-
print("Running test : API.user_login()")
21-
print(r)
14+
r = None
2215

23-
# 获取TikHub用户信息/Get TikHub user information
24-
print("Running test : API.get_user_info()")
25-
r = await api.get_user_info()
16+
# 读取用户信息/Read user information
17+
r = asyncio.run(tiktok_api.get_user_info())
2618
print(r)
2719

28-
print("\nRunning ALL TikTok methods test...\n")
20+
tiktok_video_url = 'https://www.tiktok.com/@evil0ctal/video/7156033831819037994'
21+
tiktok_music_url = 'https://www.tiktok.com/music/original-sound-7128362040359488261'
2922

30-
# 获取单个视频数据/Get single video data
31-
print("Running test : API.get_tiktok_video_data()")
32-
r = await api.get_tiktok_video_data(tiktok_url)
23+
# 解析单一tiktok视频/Parse a single tiktok video
24+
# r = asyncio.run(tiktok_api.get_tiktok_video_data(tiktok_video_url))
3325
# print(r)
3426

35-
# 获取获取用户主页的所有视频数据/Get all video data on the user's homepage
36-
print("Running test : API.get_tiktok_profile_videos()")
37-
r = await api.get_tiktok_profile_videos(tiktok_url, cursor=None, count=None, get_all=False)
38-
print(f'Get {len(r)} videos from profile')
39-
40-
# 获取用户主页的所有点赞视频数据/Get all liked video data on the user's homepage
41-
print("Running test : API.get_tiktok_profile_liked_videos()")
42-
r = await api.get_tiktok_profile_liked_videos(tiktok_url, cursor=None, count=None, get_all=False)
43-
print(f'Get {len(r)} liked videos from profile')
44-
45-
# 获取TikTok视频的所有评论数据/Get all comment data of TikTok video
46-
print("Running test : API.get_tiktok_video_comments()")
47-
r = await api.get_tiktok_video_comments(tiktok_url, cursor=None, count=None, get_all=False)
48-
print(f'Get {len(r)} comments from video')
49-
50-
# 获取音乐页面上的所有(理论上能抓取到的)视频数据/Get all (theoretically) video data on the music page
51-
print("Running test : API.get_tiktok_music_videos()")
52-
r = await api.get_tiktok_music_videos(tiktok_music_url, cursor=None, count=None, get_all=False)
53-
print(f'Get {len(r)} videos from music')
54-
55-
print("\nRunning ALL Douyin methods test...\n")
56-
57-
# 获取单个视频数据/Get single video data
58-
print("Running test : API.get_douyin_video_data()")
59-
r = await api.get_douyin_video_data(douyin_url)
60-
61-
# 获取获取用户主页的所有视频数据/Get all video data on the user's homepage
62-
print("Running test : API.get_douyin_profile_videos()")
63-
r = await api.get_douyin_profile_videos(douyin_user_url, cursor=None, count=None, get_all=False)
64-
print(f'Get {len(r)} videos from profile')
27+
# 解析tiktok用户信息/Parse tiktok user information
28+
# r = asyncio.run(tiktok_api.get_tiktok_user_data(tiktok_video_url))
29+
# print(r)
6530

66-
# 获取用户主页的所有点赞视频数据/Get all liked video data on the user's homepage
67-
print("Running test : API.get_douyin_profile_liked_videos()")
68-
r = await api.get_douyin_profile_liked_videos(douyin_user_url, cursor=None, count=None, get_all=False)
69-
print(f'Get {len(r)} liked videos from profile')
31+
# 解析tiktok用户的所有视频数据/Parse all video data of tiktok user
32+
# r = asyncio.run(tiktok_api.get_tiktok_profile_videos(tiktok_video_url, count=1))
33+
# print(r)
7034

71-
# 获取抖音视频的所有评论数据/Get all comment data of Douyin video
72-
print("Running test : API.get_douyin_video_comments()")
73-
r = await api.get_douyin_video_comments(douyin_url, cursor=None, count=None, get_all=False)
74-
print(f'Get {len(r)} comments from video')
35+
# 解析tiktok用户的所有喜欢视频数据/Parse all liked video data of tiktok user
36+
# r = asyncio.run(tiktok_api.get_tiktok_profile_liked_videos(tiktok_video_url, count=1))
37+
# print(r)
7538

76-
# 总耗时/Total time
77-
total_time = round(time.time() - start_time, 2)
78-
print("\nTest completed, total time: {}s".format(total_time))
39+
# 解析tiktok视频的所有评论数据/Parse all comment data of tiktok video
40+
# r = asyncio.run(tiktok_api.get_tiktok_video_comments(tiktok_video_url, count=1))
41+
# print(r)
7942

43+
# 解析配乐页视频数据/Parse video data of music page
44+
# r = asyncio.run(tiktok_api.get_tiktok_music_videos(tiktok_music_url, count=1))
45+
# print(r)
8046

81-
if __name__ == '__main__':
82-
api = API(
83-
email='EMAIL@EXAMPLE.COM',
84-
password='PASSWORD',
85-
proxy=None,
86-
)
87-
asyncio.run(async_test())
47+
# 解析tiktok热搜/Parse tiktok hot search
48+
r = asyncio.run(tiktok_api.get_tiktok_search_data_hot('evil0ctal'))
49+
print(r)

tikhub/AiohttpClient.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import aiohttp
2+
import asyncio
3+
4+
5+
class AiohttpClient:
6+
_instance = None
7+
8+
def __new__(cls, *args, **kwargs):
9+
if cls._instance is None:
10+
cls._instance = super().__new__(cls)
11+
return cls._instance
12+
13+
async def request(self, method, url, headers=None, params=None, data=None, json=None):
14+
"""
15+
发起单独的HTTP请求
16+
:param method: 请求方法
17+
:param url: 请求URL
18+
:param headers: 请求头
19+
:param params: URL参数
20+
:param data: 表单数据
21+
:param json: JSON数据
22+
:return: 包含响应状态码、文本和JSON的字典。
23+
"""
24+
# 发起一个单独的HTTP请求
25+
async with aiohttp.ClientSession() as session:
26+
async with session.request(method, url, headers=headers, params=params, data=data, json=json) as response:
27+
# 获取响应内容
28+
response_text = await response.text()
29+
response_json = None
30+
if response_text:
31+
try:
32+
response_json = await response.json()
33+
except Exception as e:
34+
print("Error in AiohttpClient.request when response.json():", e)
35+
# 返回响应状态码、文本和JSON
36+
# return response.status, response_text, response_json
37+
result = {
38+
'status': response.status,
39+
'text': response_text,
40+
'json': response_json
41+
}
42+
return result
43+
44+
async def make_requests(self, requests: list):
45+
"""
46+
批量发起HTTP请求
47+
:param requests: 请求列表, 列表内是元组格式,[(method, url, headers, params, data, json)]。
48+
:return: 包含所有请求结果的列表。
49+
"""
50+
# 批量发起HTTP请求
51+
async with aiohttp.ClientSession() as session:
52+
# 创建异步任务列表
53+
tasks = []
54+
for request in requests:
55+
method, url, headers, params, data, json = request
56+
task = session.request(method, url, headers=headers, params=params, data=data, json=json)
57+
tasks.append(task)
58+
# 并发处理所有请求
59+
results = []
60+
for task in asyncio.as_completed(tasks):
61+
# 等待异步任务完成
62+
response = await task
63+
# 获取响应内容
64+
response_text = await response.text()
65+
if response_text:
66+
try:
67+
response_json = await response.json()
68+
except Exception as e:
69+
response_json = None
70+
# 将结果添加到列表中
71+
results.append({
72+
str(response.url): {
73+
'method': response.method,
74+
'status': response.status,
75+
'text': response_text,
76+
'json': response_json
77+
}
78+
})
79+
# 返回所有请求的结果列表
80+
return results
81+
82+
83+
if __name__ == '__main__':
84+
# 批量发起HTTP请求
85+
requests = [
86+
# GET请求
87+
('GET', # method
88+
'https://api.tikhub.io/', # url
89+
{'Authorization': 'Bearer TOKEN'}, # headers
90+
None, None, None), # params, data, json
91+
# POST请求
92+
('POST',
93+
'https://api.tikhub.io/users/login',
94+
{'Authorization': 'Bearer TOKEN'},
95+
None, {'title': 'New post', 'content': 'Hello world!'}, None)
96+
]
97+
client = AiohttpClient()
98+
results = asyncio.run(client.make_requests(requests))
99+
print(results)

tikhub/Auth.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import asyncio
2+
import platform
3+
4+
from tikhub.AiohttpClient import AiohttpClient
5+
6+
7+
class Auth:
8+
# 初始化/initialization
9+
def __init__(self, token: str, domain: str = 'https://api.tikhub.io', proxy: str = None):
10+
super().__init__()
11+
self.token = token # Token/token
12+
self.domain = domain # 域名/domain
13+
self.proxies = proxy # HTTP代理/HTTP proxy
14+
self.headers = {'Authorization': f'Bearer {token}'} if 'bearer ' not in token.lower() else {'Authorization': token}
15+
self.client = AiohttpClient()
16+
if platform.system() == 'Windows':
17+
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
18+
19+
"""__________________________________________⬇️️认证(authenticate)⬇️️__________________________________________"""
20+
21+
# 检查Token是否过期或无效/Check if the token is expired or invalid
22+
@staticmethod
23+
async def check_token(response: dict):
24+
if response['status'] != 200:
25+
error = Exception(f'Error: {response}')
26+
raise error
27+
28+
# 获取TikHub用户信息/Get TikHub user information
29+
async def get_user_info(self) -> dict:
30+
url = f'{self.domain}/users/me/'
31+
result = await self.client.request('GET', url, self.headers, None, None, None)
32+
await self.check_token(result)
33+
return result.get('json')
34+
35+
# 每日签到/Daily check-in
36+
async def daily_check_in(self) -> dict:
37+
url = f'{self.domain}/promotion/daily_check_in'
38+
result = await self.client.request('GET', url, self.headers, None, None, None)
39+
await self.check_token(result)
40+
return result.get('json')
41+
42+
43+
if __name__ == '__main__':
44+
45+
token = input('请输入token: ')
46+
47+
auth = Auth(token)
48+
49+
r = None
50+
51+
# 读取用户信息/Read user information
52+
r = asyncio.run(auth.get_user_info())
53+
print(r)
54+
55+
# 每日签到/Daily check-in
56+
r = asyncio.run(auth.daily_check_in())
57+
print(r)
58+

0 commit comments

Comments
 (0)