Wudu
await frame.evaluate(() => { function uploadImage(url) { // Находим элемент input[type="file"] const inputElement = document.querySelector('input[type="file"]') // Создаем новый XMLHttpRequest const xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.responseType = 'blob' // Устанавливаем тип ответа как blob (двоичные данные) xhr.onload = function () { if (xhr.status === 200) { // Создаем объект File из полученных данных const blob = xhr.response const fileName = getFileNameFromUrl(url) // Функция для получения имени файла из URL const file = new File([blob], fileName, { type: 'image/jpeg' }) // Устанавливаем тип файла как image/jpeg // Создаем объект DataTransfer и добавляем в него файл const dataTransfer = new DataTransfer() dataTransfer.items.add(file) // Устанавливаем файлы в input элемент inputElement.files = dataTransfer.files // Генерируем событие change const event = new Event('change', { bubbles: true }) inputElement.dispatchEvent(event) console.log(`Файл '${fileName}' успешно добавлен в input[type='file']`) } else { console.error('Не удалось загрузить файл') } } xhr.onerror = function () { console.error('Произошла ошибка при загрузке файла') } // Отправляем запрос xhr.send() } // Функция для получения имени файла из URL function getFileNameFromUrl(url) { return url.substring(url.lastIndexOf('/') + 1) } // Использование функции для загрузки изображения // Укажите URL изображения, которое хотите загрузить const imageUrl = 'ссылка на картинку' uploadImage(imageUrl) })
Wudu
Null
Ммм, пока дочитал до этого, но похоже кукловод не поддерживает никакие вводы кроме input[type=file]
Вообще поддерживает, даже если будет кастомный div с событием drop. Решается через Input.dispatchDragEvent.
Null
Хотя, это я про CDP, не знаю как с этим именно в pptr.
Null
await frame.evaluate(() => { function uploadImage(url) { // Находим элемент input[type="file"] const inputElement = document.querySelector('input[type="file"]') // Создаем новый XMLHttpRequest const xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.responseType = 'blob' // Устанавливаем тип ответа как blob (двоичные данные) xhr.onload = function () { if (xhr.status === 200) { // Создаем объект File из полученных данных const blob = xhr.response const fileName = getFileNameFromUrl(url) // Функция для получения имени файла из URL const file = new File([blob], fileName, { type: 'image/jpeg' }) // Устанавливаем тип файла как image/jpeg // Создаем объект DataTransfer и добавляем в него файл const dataTransfer = new DataTransfer() dataTransfer.items.add(file) // Устанавливаем файлы в input элемент inputElement.files = dataTransfer.files // Генерируем событие change const event = new Event('change', { bubbles: true }) inputElement.dispatchEvent(event) console.log(`Файл '${fileName}' успешно добавлен в input[type='file']`) } else { console.error('Не удалось загрузить файл') } } xhr.onerror = function () { console.error('Произошла ошибка при загрузке файла') } // Отправляем запрос xhr.send() } // Функция для получения имени файла из URL function getFileNameFromUrl(url) { return url.substring(url.lastIndexOf('/') + 1) } // Использование функции для загрузки изображения // Укажите URL изображения, которое хотите загрузить const imageUrl = 'ссылка на картинку' uploadImage(imageUrl) })
Ох, что-то жуткое :)
Null
А зачем XMLHttpRequest? Через fetch намного проще же.
Wudu
Да я не сильно решил заморачиваться, что chatGPT дал то и поставил) Надо отрефакторить)
Null
const response = await fetch(url); const data = await response.blob(); const file = new File([data], name, { type: data.type, });
Wudu
Wudu
У меня чет кипит мозг уже
Wudu
10 часов сижу сегодня только
Null
Бывает, затягивает :)
Wudu
Еще не работал метод const clickedElement = await frame.$(el) await clickedElement.click() Если не видим объект был
Wudu
async function clickOnEl(el, frame) { await frame.waitForSelector(el, { visible: true }) const clickedElement = await frame.$(el) if (clickedElement) { await frame.evaluate((el) => { document.querySelector(el).scrollIntoView() }, el) await clickedElement.click({ delay: 100 }) console.log(`Clicked on ${el}`) } else { console.error(`Element ${el} not found`) } } Пришлось такое сделать)
Wudu
Да
Null
https://pptr.dev/api/puppeteer.elementhandle.scrollintoview
Null
А это не помогает?
Wudu
Я же добавил его)
Wudu
А так сидел мучался, не понимал почему не кликает)
Null
Я же добавил его)
Нет, ты используешь нативный метод самого JS и применяешь его внутри evaluate. А тут тебе удобная обёртка. Достаточно просто await el.scrollIntoView();.
Wudu
А, хм)
Wudu
Надо попробовать
Wudu
Просто каждый раз тестировать, уффф) Я вообще второй день с puppeteer дружить пытаюсь, еще не знаю много методов)
Wudu
Надо кукис подключить, наверное, сохранять авторизацию и входить без нее
Null
Надо кукис подключить, наверное, сохранять авторизацию и входить без нее
Так они по дефолту должны сохраняться, если указываешь userDataDir.
Wudu
Null
Но ещё есть сессионные куки, можно их перед закрытием сохранять и при открытии подгружать. Но это редко кому нужно, обычно.
Null
А куда указать?
Т.е. ты каждый раз заново авторизовываешься что ли?
Лешка
а еще локал сторедж существует
Лешка
Null
Null
а еще локал сторедж существует
Ну они по дефолту должны сохраняться же, т.е. как у обычного юзера. Хотя вот sessionStorage тоже можно вручную сохранить. Но таких ситуаций ещё меньше, думаю.
Wudu
Т.е. ты каждый раз заново авторизовываешься что ли?
Ну дыа, там суть что нужно дать несколько акков по типо login:pass login:pass login:pass login:pass
Wudu
И он в каждый заходит, регистрирует, отправляет данные
Wudu
И управление с тг бота
Null
Ну дыа, там суть что нужно дать несколько акков по типо login:pass login:pass login:pass login:pass
Так тебе просто нужно указать для каждого юзера свой каталог один раз и всё. Потом он будет автоматически авторизован. Т.е. как в обычном браузере у тебя. По дефолту куки хранятся, авторизация не слетает.
Wudu
Но если акки разные, то авторизация нужна на каждый)
Null
Но если акки разные, то авторизация нужна на каждый)
У тебя каталог с профилем будет у каждого свой и всё.
Null
profiles/1 profiles/2 profiles/3 ...
Wudu
Ну эт потом, наверное)
Wudu
Пока что я в шоке, что хотя бы это получается)
Null
А куда указать?
const browser = await puppeteer.launch({ userDataDir: "./profiles/1", });
Wudu
Но я немного застрял с геопозицией
Null
Но я немного застрял с геопозицией
Там просто укажи пустой массив, он запретит всё что не указано.
Null
const context = browser.defaultBrowserContext(); await context.overridePermissions('https://example.com', []);
Wudu
const context = browser.defaultBrowserContext(); await context.overridePermissions('https://html5demos.com', ['geolocation']);
Wudu
А вот так что он?
Null
А вот так что он?
Так он разрешит geolocation.
Wudu
Аа
Aleksey
Всем привет! У кого есть опыт поддержки сразу нескольких работающих инстансов, как вы их оркестрируете? Мне нужно держать открытыми несколько сотен браузеров и иметь возможность подключаться к ним в любое время, вот думаю, как бы это лучше организовать
Null
Всем привет! У кого есть опыт поддержки сразу нескольких работающих инстансов, как вы их оркестрируете? Мне нужно держать открытыми несколько сотен браузеров и иметь возможность подключаться к ним в любое время, вот думаю, как бы это лучше организовать
Пока самым оптимальным кажется такое решение: 1. Инстансы запускаются в докерах + xvfb + vnc 2. Инстансы запускаются на машине клиента в headless режиме + screencast 3. Web UI, в котором есть возможность запуска как в докере, так и на машине юзера в headless/headfull режиме Если запущено в докере, то смотрим/управляем через VNC, если в headless на машине юзера, то через скринкаст, если в headfull то напрямую.
Null
Докер + xvfb + vnc самый нормальный вариант. Скринкаст сильно грузит процессор.
Null
В Web UI novnc есть. В итоге получается единая панель управления.
Null
https://novnc.com/info.html
Null
В докере supervisord, который запускает и следит за vnc + xvfb + agent (который браузерами управляет).
Aleksey
Мне не нужен ui, мне достаточно и headless со скриншотами в докере Меня здесь интересует масштабирование, которое пока что я не понимаю, как организовать
Red
Guys i need bypass ozforensics who can do it with money
Null
Мне не нужен ui, мне достаточно и headless со скриншотами в докере Меня здесь интересует масштабирование, которое пока что я не понимаю, как организовать
Если речь про инфраструктуру, то Kubernetes или Docker + свой агент на каждой машине. Если о запуске самих браузеров и распределении профилей по нодам/контейнерам, то писать какой-то свой софт. Не видел ничего готового. Например, берёшь express.js и пишешь примерно такие обработчики: app.post("/api/v1/Browser/start", (req, res) => { // Поднимаешь контейнер с браузером // Подключаешься к контейнеру через puppeteer.connect }); app.post("/api/v1/Browser/stop", (req, res) => { // Останавливаешь контейнер/закрываешь браузер }); app.post("/api/v1/Browser/status", (req, res) => { // Запрашиваешь статус }); app.post("/api/v1/Browser/screenshot", async (req, res) => { // Делаешь скриншот const browser = browserList[req.body.id]; const [page] = await browser.pages(); const screen = await page.screenshot({ type: "png", }); res.set("content-type", "image/png"); res.end(screen); }); А дальше уже вызываешь API из локального софта/ui.
BЕLый
Как можно реализовать следующее. Возможность создавать профиля хром, c своими настройками(язык,UA, локация, часовой пояс и тд) Этакий аналог ffprofile но для хрома
BЕLый
Я делаю это посредством скрипта Powershell
Статью, код что угодно можешь показать?
Nessy 🫧
Статью, код что угодно можешь показать?
Вообще, я в программировании ноль, скрипт создавал с помощью ChatGPT. Думаю с помощью того же ChatGPT можно этот скрипт довести до ваших целей. Пайппеттер тоже пробовал, но работал он плохо, ошибки всякие были. # Задайте путь к исполняемому файлу Chrome $ChromePath = "C:\Program Files\Google\Chrome\Application\chrome.exe" # User Agent строка # $UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0" # Путь к папке с расширением # $ExtensionPath = "C:\Users\Sunset\Documents\Other\uBlock0.chromium" # Цикл для создания пользователей 1..10 | ForEach-Object { # Создание пользователя $UserName = "Monkey" $ProfilePath = "C:\Users\Sunset\Documents\Chrprofiles\Profile\$UserName$_" $UserDataDir = "--user-data-dir="$ProfilePath"" $LoadExtension = "--load-extension="$ExtensionPath"" # Полный аргумент для запуска Chrome $FullArguments = "$UserDataDir --user-agent="$UserAgent" $LoadExtension" # Запуск Chrome с новым пользователем и заданным User Agent и расширением Start-Process $ChromePath -ArgumentList $FullArguments # Задержка 4 секунды Start-Sleep -Seconds 4 # Создание ярлыка на рабочем столе $ShortcutPath = [System.IO.Path]::Combine([System.Environment]::GetFolderPath('Desktop'), "$UserName$_" + ".lnk") $WScriptShell = New-Object -ComObject WScript.Shell $Shortcut = $WScriptShell.CreateShortcut($ShortcutPath) $Shortcut.TargetPath = $ChromePath $Shortcut.Arguments = $FullArguments $Shortcut.Save() }
BЕLый
Понял, спасибо. Мне был важен именно подход
Null
Как можно реализовать следующее. Возможность создавать профиля хром, c своими настройками(язык,UA, локация, часовой пояс и тд) Этакий аналог ffprofile но для хрома
Есть специальный механизм policy, ты создаёшь json-файл, кладёшь его в определённый каталог и хром подхватывает из него настройки. Там довольно много настроек.
Null
https://www.chromium.org/administrators/linux-quick-start/
Null
Ну а дальше самому подготовить такой файл, и билдер к нему можно написать, на подобии ffprofile.
精神に強い
Всех приветствую, подскажите нужно следить за новостным порталом для последующего скрапа данных, лучше открывать браузер каждую минуту с новой вкладкой, проверять с базой если есть новые объявления, или же открыть сайт в новой вкладке и рефрешить страницу для последующего сравнения с базой на случай нового объявления? Какой из методов эффективнее и менее ресурсо-затратный? Спасибо
Null
Всех приветствую, подскажите нужно следить за новостным порталом для последующего скрапа данных, лучше открывать браузер каждую минуту с новой вкладкой, проверять с базой если есть новые объявления, или же открыть сайт в новой вкладке и рефрешить страницу для последующего сравнения с базой на случай нового объявления? Какой из методов эффективнее и менее ресурсо-затратный? Спасибо
1. Сначала желательно убедиться что без браузера нельзя обойтись. Бывает так, что там простой запрос JSON отдаёт. Ещё бывает что у сайта с новостями есть RSS. 2. В случае если запущен браузер и ничего не делать, то он будет занимать оперативную память и не грузить CPU 3. Если запускать раз в минуту, то это повышенная нагрузка на CPU+диск в момент запуска/закрытия
精神に強い
1. Сначала желательно убедиться что без браузера нельзя обойтись. Бывает так, что там простой запрос JSON отдаёт. Ещё бывает что у сайта с новостями есть RSS. 2. В случае если запущен браузер и ничего не делать, то он будет занимать оперативную память и не грузить CPU 3. Если запускать раз в минуту, то это повышенная нагрузка на CPU+диск в момент запуска/закрытия
Спасибо за ответ, за RSS годно, но не везде есть. Ну и есть сайты где авторизацию пройти нужно Касательно 2 и 3 лучше тогда держать постоянно запущенный и не иметь скачков по нагрузке cpu, на случай когда будет больше браузеров открыто в один момент а сервак не большой то так стабильнее будут сервисы работать? Как вот в продакшине с десятками или сотнями открытых браузеров работают? Что там за железо используется? У меня сейчас один сервис бежит который потребляет 6гб рам из 8 - один браузер который по очереди открывает 30 вкладок кликает и сохраняет текст в базу, закрывается и открывается новый с другим сайтом. Вот интересно или можно было бы оптимизировать и открыть два браузера и просто раз в минуту например обновить сайт и проверить если нет ничего нового и дальше ждать ?
Null
Спасибо за ответ, за RSS годно, но не везде есть. Ну и есть сайты где авторизацию пройти нужно Касательно 2 и 3 лучше тогда держать постоянно запущенный и не иметь скачков по нагрузке cpu, на случай когда будет больше браузеров открыто в один момент а сервак не большой то так стабильнее будут сервисы работать? Как вот в продакшине с десятками или сотнями открытых браузеров работают? Что там за железо используется? У меня сейчас один сервис бежит который потребляет 6гб рам из 8 - один браузер который по очереди открывает 30 вкладок кликает и сохраняет текст в базу, закрывается и открывается новый с другим сайтом. Вот интересно или можно было бы оптимизировать и открыть два браузера и просто раз в минуту например обновить сайт и проверить если нет ничего нового и дальше ждать ?
Всё зависит от конкретной задачи. Кому нужно много браузеров, обычно запускают в несколько потоков, например 8 штук (зависит от железа), чтобы они не мешали друг другу и гоняют по кругу. Выполнили задачу, закрыли браузер, запустили следующий. Опять же, зависит от задачи и подходов, кто-то исключительно в облаках всё запускает, им не важно 10 или 100 браузеров запустить, они платят за потраченное время/ресурсы.
Null
Спасибо за ответ, за RSS годно, но не везде есть. Ну и есть сайты где авторизацию пройти нужно Касательно 2 и 3 лучше тогда держать постоянно запущенный и не иметь скачков по нагрузке cpu, на случай когда будет больше браузеров открыто в один момент а сервак не большой то так стабильнее будут сервисы работать? Как вот в продакшине с десятками или сотнями открытых браузеров работают? Что там за железо используется? У меня сейчас один сервис бежит который потребляет 6гб рам из 8 - один браузер который по очереди открывает 30 вкладок кликает и сохраняет текст в базу, закрывается и открывается новый с другим сайтом. Вот интересно или можно было бы оптимизировать и открыть два браузера и просто раз в минуту например обновить сайт и проверить если нет ничего нового и дальше ждать ?
Только замеры тебе дадут на это ответ. Попробуй оба подхода, сделай замеры. Может 2, а может и все 4 браузера у тебя будут быстрее работать, а может оказаться так что у них постоянная конкуренция за ресурсы (CPU, диск) и один инстанс будет быстрей.
Null
Спасибо за ответ, за RSS годно, но не везде есть. Ну и есть сайты где авторизацию пройти нужно Касательно 2 и 3 лучше тогда держать постоянно запущенный и не иметь скачков по нагрузке cpu, на случай когда будет больше браузеров открыто в один момент а сервак не большой то так стабильнее будут сервисы работать? Как вот в продакшине с десятками или сотнями открытых браузеров работают? Что там за железо используется? У меня сейчас один сервис бежит который потребляет 6гб рам из 8 - один браузер который по очереди открывает 30 вкладок кликает и сохраняет текст в базу, закрывается и открывается новый с другим сайтом. Вот интересно или можно было бы оптимизировать и открыть два браузера и просто раз в минуту например обновить сайт и проверить если нет ничего нового и дальше ждать ?
Оперативная память сильно дешевле CPU, поэтому чаще всего да. Сервер с 64 Гб оперативы можно взять за 35 евро. Ты можешь запустить там минимум 64, а то и 128 браузеров. Если они не потребляют CPU особо и нет утечек памяти, они могут так долго работать.
shauryam
Last 3 month everything work fine but now I can't click on login or any button..I don't know how website understand this is automation browser Plz help me out thnx import puppeteer from 'puppeteer-extra'; import StealthPlugin from 'puppeteer-extra-plugin-stealth'; import { tableParser } from 'puppeteer-table-parser'; import puppeteers from 'puppeteer'; import axios from 'axios' ; import { RestClientV5 } from 'bybit-api'; puppeteer.use(StealthPlugin()) const browser = await puppeteer.launch({ headless:false, // Run in non-headless mode args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-setuid-sandbox', '--no-sandbox', '--single-process', '--no-zygote', '--disable-web-security', '--disable-features=site-per-process' ], ignoreDefaultArgs: ['--enable-automation'], // Ignore enable-automation flag stealth: true, // Enable stealth mode (not a standard Puppeteer option, requires additional libraries) }); const page = await browser.newPage(); await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'); await page.goto('https://www.bybit.com/en/login');
shauryam
your code not contains click button
Actually I can't even click with real mouse button..code is lengthy I just send start of it...when I open bybit now I can't click they disable something