Thank
how to set browser window visible
-
На данный момент без использования кастомного интерфейса нельзя сделать окно браузера видимым программно. Ниже proof of concept, скрипт находит в вечном цикле процесс по имени и делает его окно видимым.
Не составит труда переписать скрипт на любом другом языке и запускать его как внутри скрипта, так и снаружи BAS.
Не уверен, что запостил в нужный раздел. Так как нужно еще написать приложение для BAS на основе идеи.UPDATE: по каким-то причинам было потеряно форматирование скрипта и скрипт был восстановлен "на глаз", работоспособность не гарантируется.
import time import psutil import win32con import win32gui import win32process def windows_is_visible(pid): def enum_handler(hwnd, data): if win32process.GetWindowThreadProcessId(hwnd)[1] == pid: return True win32gui.EnumWindows(enum_handler, None) return False def window_set_visible(pid): def get_hwnds_for_pid(pid): def callback(hwnd, hwnds): _, found_pid = win32process.GetWindowThreadProcessId(hwnd) if found_pid == pid: hwnds.append(hwnd) hwnds = [] win32gui.EnumWindows(callback, hwnds) return hwnds handles = get_hwnds_for_pid(pid) if len(handles) > 0: wnd_handle = handles[0] win32gui.ShowWindow(wnd_handle, win32con.SW_SHOWNORMAL) return True return False if __name__ == '__main__': process_name = "Worker.exe" def set_visible(pid): print(window_set_visible(pid)) while True: for proc in psutil.process_iter(): if process_name in proc.name(): pid = proc.pid set_visible(pid) time.sleep(1)Ссылки по теме:
-
В данном случае как я понимаю, или 1 окно или все становятся видимыми, как у бас нельзя выбрать какое именно ?
-
@biohacker01 said in how to set browser window visible:
... все становятся видимыми...
В данном конкретном примере да.
Если нужно сделать видимым конкретный браузер, надо знать у какого процесса(с какими параметрами он был запущен) нужно это сделать.
Например, браузер запущен с параметрами где его профиль. Тогда можно найти этот конкретный процесс и изменить его видимость.
-
Вот как раз я запускаю браузеры используя
https://playwright.dev/docs/api/class-browsertype#browser-type-launch-persistent-context
то-есть указываю его путь к профилю.
Покопаюсь можно-ли эту информацию узнать у процесса -
Да в диспечерез задач можно увидеть,

что есть командная строка, а значит ее можно узнать и через API.
Все это решаем куча проблем)Спасибо за наводку
-
@biohacker01 said in how to set browser window visible:
Покопаюсь можно-ли эту информацию узнать у процесса
Можно 100%, если есть доступ к процессу в принципе. Например, если он запущен из под того же пользователя, что и скрипт, который пытается получить свойства/параметры процесса.
@biohacker01 said in how to set browser window visible:
Спасибо за наводку
Надо смотреть, как реализуется headless режим у браузеров. У меня есть смутные подозрения, что происходит ровно тоже самое, что ты пытаешься сделать сбоку.
-
@sergerdn said in how to set browser window visible:
как реализуется headless режим у браузеров
там уже давно headless new есть, который не как старый, а отрабатывает js и все остальные объекты как будто браузер включен. но да дело надо лучше изучать.
-
@sergerdn еще что интересно в BAS еще идет отрисовка мышки в IDE если запускаем, это особенности, или через js эмулируется и видно после открытия окна по WINAPI ?
-
@biohacker01 said in how to set browser window visible:
@sergerdn еще что интересно в BAS еще идет отрисовка мышки в IDE если запускаем, это особенности, или через js эмулируется и видно после открытия окна по WINAPI ?
Понятия не имею. Попробуй использовать https://github.com/CheshireCaat/playwright-with-fingerprints, там ровно тот же браузер, по крайней мере.
-
Есть интересный путь сделать то, что ты, вероятно, хочешь:
- использовать BAS GUI, чтобы задавать настройки, видеть браузеры, скрывать их и так далее.
- программировать на удобном тебе языке в обычной IDE
Я написал небольшую библиотеку, которая решают такую задачу. Так как мне самому это нужно. Есть пара не решенных вещей, для которых я пока не знаю простых путей. Например, как из стороннего скрипта передавать управление пользователю в браузере и возвращать его обратно.
Исходный код не даю, так как код пока очень сырой. В процессе его написания.
Реализация:
- BAS при старте в самом начале работы запускает скрипт cmd_initial.py в командной строке, который создает и сохраняет задания для BAS. BAS принимает задания, настраивает браузеры, стартует их.
poetry run python cmd_initial.py --bas_fingerprint_key=bla-blaПример задания:
[ { "task_id": "ecc53d50-e61b-4a8d-86d7-3b05afff060a", "browser_settings": { "components": { "widevine": "enable", "safe_browsing": "enable", "components": "enable" }, "network": { "enable_qiuc_protocol": true }, "rendering": { "maximum_fps": 30 }, "browser_version": "default", "command_line": [ "--disk-cache-size=104857600", "--disable-gpu-program-cache", "--disable-gpu-shader-disk-cache", "--disable-features=GpuProcessHighPriorityWin,GpuUseDisplayThreadPriority", "--lang=en" ], "profile": { "profile_folder_path": "C:\\Users\\Administrator\\AppData\\Local\\PyBASProfileManager\\tmp2xwpovkm", "always_load_fingerprint_from_profile_folder": false, "always_load_proxy_from_profile_folder": false }, "proxy": null, "fingerprint": { "safe_canvas": true, "use_perfect_canvas": true, "safe_webgl": true, "safe_audio": true, "safe_battery": true, "use_font_pack": true, "safe_element_size": false, "emulate_sensor_api": true, "emulate_device_scale_factor": true } } } ]- После старта браузеров каждый поток в BAS передает информацию о запущенном профиле второму скрипту cmd_worker.py.
poetry run python cmd_worker.py --bas_current_profile_id="PyBASProfileManager/tmp2xwpovkm"Что делает cmd_worker.py:
- берет информацию из параметра bas_current_profile_id, и ищет свое задание, так как мы получили полный путь к профилю. Также в процессах Windows ищет нужный запущенный браузер. Это можно понять, так как в командной строке присутствует путь к профилю.
- парсит данные командной строки, чтобы получить remote debugging port. Далее уже дело техники из него получить ws_endpoint и подключиться к нему с помощью playwright.
Скриншоты:
-
я у себя подобное реализовал, только в параметр передаю номер потока )
но все же парсинг процессов занимает 5-10 секунд, чтоб получить PID и присвоить его. -
@biohacker01 said in how to set browser window visible:
я у себя подобное реализовал, только в параметр передаю номер потока )
Не удивительно.
@biohacker01 said in how to set browser window visible:
но все же парсинг процессов занимает 5-10 секунд, чтоб получить PID и присвоить его.
Не отслеживал скорость работы. Так как я в самом начале пути. И в разрезе медленной работы самих браузеров это не так важно, так как прокси и даже умышленные замедления в работе, чтобы походить на человека.
-
@biohacker01 said in how to set browser window visible:
но все же парсинг процессов занимает 5-10 секунд, чтоб получить PID и присвоить его.
Мой сервер https://www.hetzner.com/dedicated-rootserver/ax41-nvme.
Время поиска процесса по cmd, где есть нужный профиль в параметрах. Надо смотреть на твою реализацию, почему у тебя так долго.
$ cat logs/cmd_worker.log | grep "_find_proc" 2023-10-04 05:44:08,851 21432 DEBUG [utils] func:'_find_proc' took: 0.0350 sec 2023-10-04 05:44:08,879 17828 DEBUG [utils] func:'_find_proc' took: 0.0780 sec 2023-10-04 05:44:10,105 6716 DEBUG [utils] func:'_find_proc' took: 0.0564 sec 2023-10-04 05:44:11,174 9724 DEBUG [utils] func:'_find_proc' took: 0.0530 sec 2023-10-04 05:44:16,793 21784 DEBUG [utils] func:'_find_proc' took: 0.1097 sec 2023-10-04 05:44:18,010 17728 DEBUG [utils] func:'_find_proc' took: 0.0208 sec 2023-10-04 05:44:18,736 17292 DEBUG [utils] func:'_find_proc' took: 0.0744 sec 2023-10-04 05:44:25,833 18756 DEBUG [utils] func:'_find_proc' took: 0.0963 sec 2023-10-04 05:44:29,011 18472 DEBUG [utils] func:'_find_proc' took: 0.0475 sec 2023-10-04 05:44:30,689 14280 DEBUG [utils] func:'_find_proc' took: 0.0777 secФункция:
import os import psutil from pydantic import FilePath _worker_proc_name = "Worker.exe" # Worker browser process (mother) _browser_proc_name = "worker.exe" # Chromium browser process (child) def _find_proc(profile_folder_path: FilePath) -> int: """ Find and return the process ID of a Chromium browser instance with a specific profile folder path. Parameters: - profile_folder_path (FilePath): The path of the profile folder to search for. Returns: - int: The process ID (PID) of the matching browser instance, or 0 if not found. """ # Iterate through all running processes for proc in psutil.process_iter(): name = proc.name() # Check if the process is a Worker.exe process if name == _worker_proc_name: for child in proc.children(recursive=False): # Check if the child process is the browser process if child.name() == _browser_proc_name: cmd_line = child.cmdline() for line in cmd_line: line = line.strip() # Check if the command line argument specifies the user data directory if not line.startswith("--user-data-dir="): continue # Extract the user data directory path _, profile_dir = line.split("--user-data-dir=") profile_dir = os.path.normpath(profile_dir) # Compare the user data directory path with the provided profile folder path if FilePath(profile_dir) == profile_folder_path: return child.pid # Return the process ID if a match is found return 0 # Return 0 if no matching process is found -
@biohacker01 said in how to set browser window visible:
@sergerdn еще что интересно в BAS еще идет отрисовка мышки в IDE если запускаем, это особенности, или через js эмулируется и видно после открытия окна по WINAPI ?
BAS эмулирует движения мыши через свой внутренний API, если использовать браузер не из BAS, то данная фича будет недоступна. В том числе если использовать и https://wiki.bablosoft.com/doku.php?id=puppeteerwithfingerprints#how_to_start.
Чтобы была возможность использовать эту фичу, нужно запускать браузер именно из BAS.
Но если набросать скрипт из двух кубиков, а потом открыть консоль браузера, то там будет куча логов, что мышка двигалась.

addEventListener("mousemove", (event) => { console.log(`Mouse X: ${event.clientX}, Mouse Y: ${event.clientY}`); });Пример реализации, что сделал я:
-
@Poisen said in how to set browser window visible:
Может ксть идеи как через стандартный интерфейс в скомпилированном скрипте с включенной галкой "скрыть браузеры" передать управление браузером пользователю?
Это галка скрывает меню, а не сами браузеры.
Я не тестил, но вероятно, можно попробовать сделать браузер видимым сбоку и все так же передать управление пользователю.
-
@sergerdn said in how to set browser window visible:
import time
import psutil
import win32con
import win32gui
import win32processdef windows_is_visible(pid):
def enum_handler(hwnd, data):
if win32process.GetWindowThreadProcessId(hwnd)[1] == pid:
return Truewin32gui.EnumWindows(enum_handler, None) return Falsedef window_set_visible(pid):
def get_hwnds_for_pid(pid):
def callback(hwnd, hwnds):
_, found_pid = win32process.GetWindowThreadProcessId(hwnd)
if found_pid == pid:
hwnds.append(hwnd)hwnds = [] win32gui.EnumWindows(callback, hwnds) return hwnds handles = get_hwnds_for_pid(pid) if len(handles) > 0: wnd_handle = handles[0] win32gui.ShowWindow(wnd_handle, win32con.SW_SHOWNORMAL) return True return Falseif name == 'main':
process_name = "Worker.exe"def set_visible(pid): print(window_set_visible(pid)) while True: for proc in psutil.process_iter(): if process_name in proc.name(): pid = proc.pid set_visible(pid) time.sleep(1)where to put this script on the bas?