mirror of
https://github.com/browser-use/browser-use
synced 2026-05-13 17:56:35 +02:00
237 lines
6.4 KiB
Python
237 lines
6.4 KiB
Python
"""
|
|
Description: These Python modules are designed to capture detailed
|
|
browser usage datafor analysis, with both server and client
|
|
components working together to record and store the information.
|
|
|
|
Author: Carlos A. Planchón
|
|
https://github.com/carlosplanchon/
|
|
|
|
Adapt this code to your needs.
|
|
|
|
Feedback is appreciated!
|
|
"""
|
|
|
|
#####################
|
|
# #
|
|
# --- UTILS --- #
|
|
# #
|
|
#####################
|
|
|
|
import base64
|
|
|
|
|
|
def b64_to_png(b64_string: str, output_file):
|
|
"""
|
|
Convert a Base64-encoded string to a PNG file.
|
|
|
|
:param b64_string: A string containing Base64-encoded data
|
|
:param output_file: The path to the output PNG file
|
|
"""
|
|
with open(output_file, 'wb') as f:
|
|
f.write(base64.b64decode(b64_string))
|
|
|
|
|
|
###################################################################
|
|
# #
|
|
# --- FASTAPI API TO RECORD AND SAVE Browser-Use ACTIVITY --- #
|
|
# #
|
|
###################################################################
|
|
|
|
# Save to api.py and run with `python api.py`
|
|
|
|
# ! pip install uvicorn
|
|
# ! pip install fastapi
|
|
# ! pip install prettyprinter
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
import prettyprinter
|
|
from fastapi import FastAPI, Request
|
|
|
|
prettyprinter.install_extras()
|
|
|
|
app = FastAPI()
|
|
|
|
|
|
@app.post('/post_agent_history_step')
|
|
async def post_agent_history_step(request: Request):
|
|
data = await request.json()
|
|
prettyprinter.cpprint(data)
|
|
|
|
# Ensure the "recordings" folder exists using pathlib
|
|
recordings_folder = Path('recordings')
|
|
recordings_folder.mkdir(exist_ok=True)
|
|
|
|
# Determine the next file number by examining existing .json files
|
|
existing_numbers = []
|
|
for item in recordings_folder.iterdir():
|
|
if item.is_file() and item.suffix == '.json':
|
|
try:
|
|
file_num = int(item.stem)
|
|
existing_numbers.append(file_num)
|
|
except ValueError:
|
|
# In case the file name isn't just a number
|
|
...
|
|
|
|
if existing_numbers:
|
|
next_number = max(existing_numbers) + 1
|
|
else:
|
|
next_number = 1
|
|
|
|
# Construct the file path
|
|
file_path = recordings_folder / f'{next_number}.json'
|
|
|
|
# Save the JSON data to the file
|
|
with file_path.open('w') as f:
|
|
json.dump(data, f, indent=2)
|
|
|
|
return {'status': 'ok', 'message': f'Saved to {file_path}'}
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import uvicorn
|
|
|
|
uvicorn.run(app, host='0.0.0.0', port=9000)
|
|
|
|
|
|
##############################################################
|
|
# #
|
|
# --- CLIENT TO RECORD AND SAVE Browser-Use ACTIVITY --- #
|
|
# #
|
|
##############################################################
|
|
|
|
"""
|
|
pyobjtojson:
|
|
|
|
A Python library to safely and recursively serialize any Python object
|
|
(including Pydantic models and dataclasses) into JSON-ready structures,
|
|
gracefully handling circular references.
|
|
"""
|
|
|
|
# ! pip install -U pyobjtojson
|
|
# ! pip install -U prettyprinter
|
|
|
|
import asyncio
|
|
import os
|
|
import sys
|
|
|
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
import requests
|
|
from langchain_openai import ChatOpenAI
|
|
from pyobjtojson import obj_to_json
|
|
|
|
from browser_use import Agent
|
|
|
|
# import prettyprinter
|
|
# prettyprinter.install_extras()
|
|
|
|
|
|
def send_agent_history_step(data):
|
|
url = 'http://127.0.0.1:9000/post_agent_history_step'
|
|
response = requests.post(url, json=data)
|
|
return response.json()
|
|
|
|
|
|
async def record_activity(agent_obj):
|
|
website_html = None
|
|
website_screenshot = None
|
|
urls_json_last_elem = None
|
|
model_thoughts_last_elem = None
|
|
model_outputs_json_last_elem = None
|
|
model_actions_json_last_elem = None
|
|
extracted_content_json_last_elem = None
|
|
|
|
print('--- ON_STEP_START HOOK ---')
|
|
website_html: str = await agent_obj.browser_context.get_page_html()
|
|
website_screenshot: str = await agent_obj.browser_context.take_screenshot()
|
|
|
|
print('--> History:')
|
|
if hasattr(agent_obj, 'state'):
|
|
history = agent_obj.state.history
|
|
else:
|
|
history = None
|
|
|
|
model_thoughts = obj_to_json(obj=history.model_thoughts(), check_circular=False)
|
|
|
|
# print("--- MODEL THOUGHTS ---")
|
|
if len(model_thoughts) > 0:
|
|
model_thoughts_last_elem = model_thoughts[-1]
|
|
# prettyprinter.cpprint(model_thoughts_last_elem)
|
|
|
|
# print("--- MODEL OUTPUT ACTION ---")
|
|
model_outputs = agent_obj.state.history.model_outputs()
|
|
model_outputs_json = obj_to_json(obj=model_outputs, check_circular=False)
|
|
|
|
if len(model_outputs_json) > 0:
|
|
model_outputs_json_last_elem = model_outputs_json[-1]
|
|
# prettyprinter.cpprint(model_outputs_json_last_elem)
|
|
|
|
# print("--- MODEL INTERACTED ELEM ---")
|
|
model_actions = agent_obj.state.history.model_actions()
|
|
model_actions_json = obj_to_json(obj=model_actions, check_circular=False)
|
|
|
|
if len(model_actions_json) > 0:
|
|
model_actions_json_last_elem = model_actions_json[-1]
|
|
# prettyprinter.cpprint(model_actions_json_last_elem)
|
|
|
|
# print("--- EXTRACTED CONTENT ---")
|
|
extracted_content = agent_obj.state.history.extracted_content()
|
|
extracted_content_json = obj_to_json(obj=extracted_content, check_circular=False)
|
|
if len(extracted_content_json) > 0:
|
|
extracted_content_json_last_elem = extracted_content_json[-1]
|
|
# prettyprinter.cpprint(extracted_content_json_last_elem)
|
|
|
|
# print("--- URLS ---")
|
|
urls = agent_obj.state.history.urls()
|
|
# prettyprinter.cpprint(urls)
|
|
urls_json = obj_to_json(obj=urls, check_circular=False)
|
|
|
|
if len(urls_json) > 0:
|
|
urls_json_last_elem = urls_json[-1]
|
|
# prettyprinter.cpprint(urls_json_last_elem)
|
|
|
|
model_step_summary = {
|
|
'website_html': website_html,
|
|
'website_screenshot': website_screenshot,
|
|
'url': urls_json_last_elem,
|
|
'model_thoughts': model_thoughts_last_elem,
|
|
'model_outputs': model_outputs_json_last_elem,
|
|
'model_actions': model_actions_json_last_elem,
|
|
'extracted_content': extracted_content_json_last_elem,
|
|
}
|
|
|
|
print('--- MODEL STEP SUMMARY ---')
|
|
# prettyprinter.cpprint(model_step_summary)
|
|
|
|
send_agent_history_step(data=model_step_summary)
|
|
|
|
# response = send_agent_history_step(data=history)
|
|
# print(response)
|
|
|
|
# print("--> Website HTML:")
|
|
# print(website_html[:200])
|
|
# print("--> Website Screenshot:")
|
|
# print(website_screenshot[:200])
|
|
|
|
|
|
agent = Agent(
|
|
task='Compare the price of gpt-4o and DeepSeek-V3',
|
|
llm=ChatOpenAI(model='gpt-4o'),
|
|
)
|
|
|
|
|
|
async def run_agent():
|
|
try:
|
|
await agent.run(on_step_start=record_activity, max_steps=30)
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
|
|
asyncio.run(run_agent())
|