Pyppeteer connection closed after a minute - python

Good day everyone. I ran this code and it works perfectly well.the main purpose is to capture websocket traffic and the problem is that it closes after a minute or there about.. please how can I fix this.. I want it to stay alive forever
import asyncio
from pyppeteer import launch
async def main():
browser = await launch(
headless=True,
args=['--no-sandbox'],
autoClose=False
)
page = await browser.newPage()
await page.goto('https://www.tradingview.com/symbols/BTCUSD/')
cdp = await page.target.createCDPSession()
await cdp.send('Network.enable')
await cdp.send('Page.enable')
def printResponse(response):
print(response)
cdp.on('Network.webSocketFrameReceived', printResponse) # Calls printResponse when a websocket is received
cdp.on('Network.webSocketFrameSent', printResponse) # Calls printResponse when a websocket is sent
await asyncio.sleep(100)
asyncio.get_event_loop().run_until_complete(main())

Related

Python websockets fast one way but 10x slower with response

I have a sanic webserver running websockets, behind the scenes its using the "websockets" library.
Server
from asyncio import sleep
from sanic import Sanic
app = Sanic("websocket test")
#app.websocket("/")
async def test(_, ws):
while True:
data = await ws.recv()
data = await ws.send('Hi')
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000)
Client
import asyncio
import websockets
async def hello():
uri = "ws://localhost:8000"
async with websockets.connect(uri) as websocket:
while iteration:
await websocket.send("Hi")
await websocket.recv()
asyncio.get_event_loop().run_until_complete(hello())
When I remove ws.send('Hi') from the server and await websocket.recv() from the client i can get 58000 messages a second, once I start listening for a response it goes all the way down to 6000 messages a second, I am just curious what is making this run 10x slower when the server responds.
I think the solution here would be to seperate your send and recv into seperate tasks so they can yield concurrently.
async def producer(send):
while True:
await send("...")
await asyncio.sleep(1)
async def consumer(recv):
while True:
message = await recv
print(message)
async def test(request, ws):
request.app.add_task(producer(ws.send)))
request.app.add_task(consumer(ws.recv))
Obviously, this is a very simple example, and at the very least you should use some sort of a Queue for your producer.
But, when you break them into seperate tasks, then your recv is not blocked by send.

Execute async request every N seconds while websocket keeps streaming python

Using Async with websocket and web requests, how does one continuously watch data from websocket while also, with N seconds interval, updating data from web request.
I've tried different versions of
async def websocket_stream():
while True:
get_data_from_stream()
do_stuff_with_data()
async def web_requests():
await asyncio.sleep(30)
async with httpx.AsyncClient() as client:
for n in list_of_things:
html= client.get('www.webpage.com/stuff')
do_other_stuff_with_data(html)
async def do_sometimes(timeout, stuff):
while True:
await asyncio.sleep(timeout)
await stuff()
async def do_nonstop(stuff):
while True:
await stuff()
taskone=asyncio.create_task(do_nonstop(web_stream))
tasktwo=asyncio.create_task(do_sometimes(10, web_request()))
Which obviously doesnt work and just streams web_streams.
How do I define so that web_request() only does one loop thru list_of_things and then sleeps for N seconds while web_streams() websocket keeps streaming?

Python websockets client keep connection open

In Python, I'm using "websockets" library for websocket client.
import asyncio
import websockets
async def init_sma_ws():
uri = "wss://echo.websocket.org/"
async with websockets.connect(uri) as websocket:
name = input("What's your name? ")
await websocket.send('name')
greeting = await websocket.recv()
The problem is the client websocket connection is disconnected once a response is received. I want the connection to remain open so that I can send and receive messages later.
What changes do I need to keep the websocket open and be able to send and receive messages later?
I think your websocket is disconnected due to exit from context manager after recv().
Such code works perfectly:
import asyncio
import websockets
async def init_sma_ws():
uri = "wss://echo.websocket.org/"
async with websockets.connect(uri) as websocket:
while True:
name = input("What's your name? ")
if name == 'exit':
break
await websocket.send(name)
print('Response:', await websocket.recv())
asyncio.run(init_sma_ws())
In your approach you used a asynchronous context manager which closes a connection when code in the block is executed. In the example below an infinite asynchronous iterator is used which keeps the connection open.
import asyncio
import websockets
async def main():
async for websocket in websockets.connect(...):
try:
...
except websockets.ConnectionClosed:
continue
asyncio.run(main())
More info in library's docs.

Python: keep open browser in pyppeteer and create CDPSession

I've got two issues that I can't solve it at them moment.
1. I would like to keep the browser running so I could just re-connect using pyppeteer.launcher.connect() function but it seems to be closed imidiately even if I don't call pyppeteer.browser.Browser.close().
test01.py:
import asyncio
from pyppeteer import launch, connect
async def fetch():
browser = await launch(
headless=False,
args=['--no-sandbox']
)
print(f'Endpoint: {browser.wsEndpoint}')
await browser.disconnect()
loop = asyncio.get_event_loop()
loop.run_until_complete(fetch())
$ python test01.py
Endpoint: ws://127.0.0.1:51757/devtools/browser/00e917a9-c031-499a-a8ee-ca4090ebd3fe
$ curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" http://127.0.0.1:51757
curl: (7) Failed to connect to 127.0.0.1 port 51757: Connection refused
2. How do I create CDP session. This code should open another browser window but it doesn't work as expected:
test02.py
import asyncio
import time
from pyppeteer import launch, connect
async def fetch():
browser = await launch(
headless=False,
args=['--no-sandbox']
)
page = await browser.newPage()
cdp = await page.target.createCDPSession()
await cdp.send('Target.createBrowserContext')
time.sleep(5)
await browser.disconnect()
loop = asyncio.get_event_loop()
loop.run_until_complete(fetch())
$ python test02.py
Future exception was never retrieved
future: <Future finished exception=NetworkError('Protocol error Target.sendMessageToTarget: Target closed.',)>
pyppeteer.errors.NetworkError: Protocol error Target.sendMessageToTarget: Target closed.
How to keep the browser running
You just need to use autoClose flag, here's the docs:
autoClose (bool): Automatically close browser process when script
completed. Defaults to True.
In this case you test01.py would look as follows:
import asyncio
from pyppeteer import launch, connect
async def fetch():
browser = await launch(
headless=False,
args=['--no-sandbox'],
autoClose=False
)
print(f'Endpoint: {browser.wsEndpoint}')
await browser.disconnect()
loop = asyncio.get_event_loop()
loop.run_until_complete(fetch())
CDP session
Here it is:
import asyncio
import time
from pprint import pprint
from pyppeteer import launch, connect
from pyppeteer.browser import BrowserContext
async def fetch():
browser = await launch(
headless=False,
args=['--no-sandbox'],
autoClose=False
)
page = await browser.newPage()
cdp = await page.target.createCDPSession()
raw_context = await cdp.send('Target.createBrowserContext')
pprint(raw_context)
context = BrowserContext(browser, raw_context['browserContextId'])
new_page = await context.newPage()
await cdp.detach()
await browser.disconnect()
loop = asyncio.get_event_loop()
loop.run_until_complete(fetch())
Inspired by Browser.createIncognitoBrowserContext from pyppeteer itself.
Notice creating additional sessions via CDP doesn't seem to be such a great idea because browser._contexts won't be updated and will become inconsistent. It's also likely that Browser.createIncognitoBrowserContext might fit your needs without resorting to CDP whatsoever

Socket Listen for Events While Running Heartbeat

I am trying to setup a listener for socket events while concurrently sending a ping message in the background.
The message received events fire, but only after the next ping completes. There seems to be something blocking.
Here's a mockup of the code I'm running.
import asyncio
import websockets
message = "First Message"
ping = "ping"
url = 'www.socketurl.com'
async def consumer_handler(websocket):
message = await websocket.recv()
if message:
print(message)
async def pingFunc(socket):
await asyncio.sleep(4)
await socket.send(ping)
async def connect(uri):
async with websockets.connect(uri,timeout=5) as websocket:
await websocket.send(message) #send hello message that returns a few pieces of info
while True:
await consumer_handler(websocket) #wait for messages and handle them
await pingFunc(websocket) #keep the connection alive
loop = asyncio.get_event_loop()
loop.run_until_complete(
connect(url)
)

Categories