dfreelon / pyktok

A simple module to collect video, text, and metadata from Tiktok.
BSD 3-Clause "New" or "Revised" License
316 stars 44 forks source link

'TikTokApi' object has no attribute 'browser' #62

Closed LikeADemonicMind closed 3 weeks ago

LikeADemonicMind commented 3 weeks ago

Hi! I hope you're doing well.

I've seen that you updated PykTok on July and that save_tiktok_multi_page worked again, so I wanted to try it out! Unfortunately, I've got an error while trying to launch my code: 'TikTokApi' object has no attribute 'browser'

Here's my code: import nest_asyncio # needed because of the "asyncio.run() cannot be called from a running event loop pyktok" error nest_asyncio.apply() import pyktok as pyk pyk.save_tiktok_multi_page('yourgirlangeel', save_video=False,metadata_fn='tiktok.csv')

Here's the full cell output:

NotImplementedError Traceback (most recent call last) File ~\anaconda3\envs\chatbot\Lib\site-packages\pyktok\pyktok.py:340, in get_video_urls(tt_ent, ent_type, video_ct, headless) 339 async with TikTokApi() as api: --> 340 await api.create_sessions(headless=headless, 341 ms_tokens=[ms_token], 342 num_sessions=1, 343 sleep_after=3, 344 context_options=context_dict) 345 if ent_type == 'user':

File ~\anaconda3\envs\chatbot\Lib\site-packages\TikTokApi\tiktok.py:245, in TikTokApi.create_sessions(self, num_sessions, headless, ms_tokens, proxies, sleep_after, starting_url, context_options, override_browser_args, cookies, suppress_resource_load_types, browser, executable_path) 218 """ 219 Create sessions for use within the TikTokApi class. 220 (...) 243 await api.create_sessions(num_sessions=5, ms_tokens=['msToken1', 'msToken2']) 244 """ --> 245 self.playwright = await async_playwright().start() 246 if browser == "chromium":

File ~\anaconda3\envs\chatbot\Lib\site-packages\playwright\async_api_context_manager.py:51, in PlaywrightContextManager.start(self) 50 async def start(self) -> AsyncPlaywright: ---> 51 return await self.aenter()

File ~\anaconda3\envs\chatbot\Lib\site-packages\playwright\async_api_context_manager.py:46, in PlaywrightContextManager.aenter(self) 45 playwright_future.cancel() ---> 46 playwright = AsyncPlaywright(next(iter(done)).result()) 47 playwright.stop = self.aexit # type: ignore

File ~\anaconda3\envs\chatbot\Lib\asyncio\futures.py:203, in Future.result(self) 202 if self._exception is not None: --> 203 raise self._exception.with_traceback(self._exception_tb) 204 return self._result

File ~\anaconda3\envs\chatbot\Lib\site-packages\playwright_impl_transport.py:120, in PipeTransport.connect(self) 119 executable_path, entrypoint_path = compute_driver_executable() --> 120 self._proc = await asyncio.create_subprocess_exec( 121 executable_path, 122 entrypoint_path, 123 "run-driver", 124 stdin=asyncio.subprocess.PIPE, 125 stdout=asyncio.subprocess.PIPE, 126 stderr=_get_stderr_fileno(), 127 limit=32768, 128 env=env, 129 startupinfo=startupinfo, 130 ) 131 except Exception as exc:

File ~\anaconda3\envs\chatbot\Lib\asyncio\subprocess.py:223, in create_subprocess_exec(program, stdin, stdout, stderr, limit, *args, *kwds) 221 protocol_factory = lambda: SubprocessStreamProtocol(limit=limit, 222 loop=loop) --> 223 transport, protocol = await loop.subprocess_exec( 224 protocol_factory, 225 program, args, 226 stdin=stdin, stdout=stdout, 227 stderr=stderr, **kwds) 228 return Process(transport, protocol, loop)

File ~\anaconda3\envs\chatbot\Lib\asyncio\base_events.py:1694, in BaseEventLoop.subprocess_exec(self, protocol_factory, program, stdin, stdout, stderr, universal_newlines, shell, bufsize, encoding, errors, text, *args, kwargs) 1693 self._log_subprocess(debug_log, stdin, stdout, stderr) -> 1694 transport = await self._make_subprocess_transport( 1695 protocol, popen_args, False, stdin, stdout, stderr, 1696 bufsize, kwargs) 1697 if self._debug and debug_log is not None:

File ~\anaconda3\envs\chatbot\Lib\asyncio\base_events.py:502, in BaseEventLoop._make_subprocess_transport(self, protocol, args, shell, stdin, stdout, stderr, bufsize, extra, **kwargs) 501 """Create subprocess transport.""" --> 502 raise NotImplementedError

NotImplementedError:

During handling of the above exception, another exception occurred:

AttributeError Traceback (most recent call last) Cell In[10], line 1 ----> 1 pyk.save_tiktok_multi_page('tiktok', save_video=False,metadata_fn='tiktok.csv')

File ~\anaconda3\envs\chatbot\Lib\site-packages\pyktok\pyktok.py:394, in save_tiktok_multi_page(tt_ent, ent_type, video_ct, headless, save_video, metadata_fn, sleep, browser_name) 386 def save_tiktok_multi_page(tt_ent, 387 ent_type="user", 388 video_ct=30, (...) 392 sleep=4, 393 browser_name=None): --> 394 video_urls = asyncio.run(get_video_urls(tt_ent, 395 ent_type, 396 video_ct, 397 headless)) 398 save_tiktok_multi_urls(video_urls, 399 save_video, 400 metadata_fn, 401 sleep, 402 browser_name)

File ~\anaconda3\envs\chatbot\Lib\site-packages\nest_asyncio.py:30, in _patch_asyncio..run(main, debug) 28 task = asyncio.ensure_future(main) 29 try: ---> 30 return loop.run_until_complete(task) 31 finally: 32 if not task.done():

File ~\anaconda3\envs\chatbot\Lib\site-packages\nest_asyncio.py:98, in _patch_loop..run_until_complete(self, future) 95 if not f.done(): 96 raise RuntimeError( 97 'Event loop stopped before Future completed.') ---> 98 return f.result()

File ~\anaconda3\envs\chatbot\Lib\asyncio\futures.py:203, in Future.result(self) 201 self.__log_traceback = False 202 if self._exception is not None: --> 203 raise self._exception.with_traceback(self._exception_tb) 204 return self._result

File ~\anaconda3\envs\chatbot\Lib\asyncio\tasks.py:277, in Task.step(failed resolving arguments) 273 try: 274 if exc is None: 275 # We use the send method directly, because coroutines 276 # don't have `iterandnext__` methods. --> 277 result = coro.send(None) 278 else: 279 result = coro.throw(exc)

File ~\anaconda3\envs\chatbot\Lib\site-packages\pyktok\pyktok.py:339, in get_video_urls(tt_ent, ent_type, video_ct, headless) 336 url_p2 = "/video/" 337 tt_list = [] --> 339 async with TikTokApi() as api: 340 await api.create_sessions(headless=headless, 341 ms_tokens=[ms_token], 342 num_sessions=1, 343 sleep_after=3, 344 context_options=context_dict) 345 if ent_type == 'user':

File ~\anaconda3\envs\chatbot\Lib\site-packages\TikTokApi\tiktok.py:493, in TikTokApi.aexit(self, exc_type, exc, tb) 491 async def aexit(self, exc_type, exc, tb): 492 await self.close_sessions() --> 493 await self.stop_playwright()

File ~\anaconda3\envs\chatbot\Lib\site-packages\TikTokApi\tiktok.py:480, in TikTokApi.stop_playwright(self) 478 async def stop_playwright(self): 479 """Stop the playwright browser""" --> 480 await self.browser.close() 481 await self.playwright.stop()

AttributeError: 'TikTokApi' object has no attribute 'browser'

I've already tried the solution here #61 but it doesn't work for me... Here are the versions of all of my packages: pyktok : 0.0.29 beautifulsoup : 4.12.3 browser-cookie3 : 0.19.1 numpy : 1.26.4 pandas : 2.2.0 requests : 2.32.3 tiktokapi : 6.4.0 python version : 3.11.7

Thanks a lot for your work!

dfreelon commented 3 weeks ago

Hello. Can you please state the IDE and OS you are using? Thanks.

LikeADemonicMind commented 3 weeks ago

I'm working on Jupyter Lab and on Windows 10 Pro.

dfreelon commented 3 weeks ago

I just tested your code and it worked fine for me. You may need to try it out in a console or PowerShell window. You shouldn't need to run import nest_asyncio, it should work fine with the following two statements only.

LikeADemonicMind commented 3 weeks ago

You're right, I don't have this error anymore but get this one instead : TikTokApi.exceptions.EmptyResponseException: None -> TikTok returned an empty response

Can you give me the version of the TikTokApi you're using please?

dfreelon commented 3 weeks ago

That is an upstream error, which means the code did what it was supposed to but TikTok basically blocked you. Here are some solutions to try:

dfreelon commented 3 weeks ago

Also I'm using TikTokApi 6.3.0

LikeADemonicMind commented 3 weeks ago

Thanks for your advices! I've downgraded TikTokApi. It works for hashtags and for some users but not all of them... I don't know why but I'll try to figure it out.

dfreelon commented 3 weeks ago

Good luck!

LikeADemonicMind commented 3 weeks ago

Thanks! So, I realized that it works for european creators (I'm in Europe) but not others... maybe a geographic limitation!

dfreelon commented 3 weeks ago

Interesting... you could potentially use a VPN to get around that.