Поиск в Google по драматургу

Я пытаюсь выполнить поиск в Google с помощью драматурга. Но получаю эту ошибку:

playwright._impl._errors.TimeoutError: Page.fill: Timeout 60000ms exceeded.
Call log:
waiting for locator("input[name=\"q\"]")

Вот код:

from playwright.async_api import async_playwright
import asyncio


async def main():
    async with async_playwright() as pw:
        browser = await pw.chromium.launch(args=["--disable-gpu", "--single-process", "--headless=new"], headless=True)

        page = await browser.new_page()

        # Go to Google
        await page.goto('https://www.google.com')

        # Accept the cookies prompt (if it appears)
        try:
            accept_button = await page.wait_for_selector('button:has-text("I agree")', timeout=5000)
            if accept_button:
                await accept_button.click()
        except:
            pass

        # Search for a query
        query = "Playwright Python"
        await page.fill('input[name = "q"]', query, timeout=60000)
        await page.press('input[name = "q"]', 'Enter')

        # Wait for the results to load
        await page.wait_for_selector('h3')

        # Extract the first result's link
        first_result = await page.query_selector('h3')
        first_link = await first_result.evaluate('(element) => element.closest("a").href')
        print("First search result link:", first_link)

        await browser.close()

if __name__ == '__main__':
    asyncio.run(main())

Зачем полагаться на автоматизацию главной страницы, если можно сразу перейти к результатам? page.goto("https://www.google.com/search?q=playwright+python‌​", wait_until = "commit").

ggorlen 26.08.2024 06:51

Этот элемент не input, а textarea

I.sh. 26.08.2024 08:59
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как упоминалось в комментарии , замена input на textarea решает проблему.

Тем не менее, распространенная XY-проблема/антипаттерн в парсинге предполагает, что вы должны действовать как человек. Это касается только тестирования. При парсинге вы можете использовать ярлыки, которые позволят получить результат быстрее, надежнее и с меньшим количеством кода. Пропускайте посторонние страницы, не нажимайте кнопки без необходимости, удаляйте баннеры cookie вместо того, чтобы покорно их принимать, пропускайте проверки видимости и доверенные события. Вы даже можете перехватывать запросы или напрямую обращаться к API.

Применив это на практике, вы можете перейти непосредственно к странице результатов с помощью одной навигации и покончить с этим, избегая суеты, медлительности и ненадежности автоматизации целевой страницы:

import asyncio
import urllib.parse
from playwright.async_api import async_playwright  # 1.44.0


async def main():
    term = urllib.parse.quote_plus("playwright python")
    url = f"https://www.google.com/search?q = {term}"

    async with async_playwright() as pw:
        browser = await pw.chromium.launch()
        page = await browser.new_page()
        await page.goto(url, wait_until = "domcontentloaded")
        link = await page.locator("h3").first.evaluate('el => el.closest("a").href')
        print("First search result link:", link)
        await browser.close()


if __name__ == "__main__":
    asyncio.run(main())

Избегайте wait_for_selector и query_selector — отдайте предпочтение локаторам.

Кроме того, данные находятся в статическом HTML-коде, так что вам даже не понадобится Playwright, если вам удобно немного обрабатывать URL-адреса (Google по какой-то причине запутывает результаты):

import re
import urllib.parse
from bs4 import BeautifulSoup  # 4.10.0
from requests import get  # 2.31.0


term = urllib.parse.quote_plus("playwright python")
response = get(f"https://www.google.com/search?q = {term}")
response.raise_for_status()
soup = BeautifulSoup(response.text, "lxml")  # 4.8.0
link = soup.select_one("h3").find_parent("a")["href"].replace(r"/url?q = ", "")
link = re.sub(r"&sa=U&.*", "", link)
print("First search result link:", link)

Тест скорости:

# OP's playwright script after the input -> textarea fix
real 0m7.487s
user 0m2.804s
sys  0m0.438s

# my playwright script
real 0m1.046s
user 0m0.539s
sys  0m0.136s

# requests/beautiful soup
real 0m0.521s
user 0m0.157s
sys  0m0.023s

В некоторых случаях может быть полезно заблокировать запросы к ненужным вам ресурсам, таким как изображения, таблицы стилей и т. д., и отключить JS. Вот пример того, как это сделать для потомков, но в данном случае это не поможет, вероятно, потому, что загрузка Google довольно быстрая и JS-light уже:

import asyncio
import urllib.parse
from playwright.async_api import async_playwright


async def main():
    term = urllib.parse.quote_plus("playwright python")
    url = f"https://www.google.com/search?q = {term}"

    async def handle_requests(route, request):
        if request.url.startswith(url):
            await route.continue_()
        else:
            await route.abort()

    async with async_playwright() as pw:
        browser = await pw.chromium.launch()
        context = await browser.new_context(java_script_enabled=False)
        page = await context.new_page()
        await page.route("**/*", handle_requests)
        await page.goto(url, wait_until = "domcontentloaded")
        link = await page.locator("h3").first.evaluate('el => el.closest("a").href')
        print("First search result link:", link)
        await browser.close()


if __name__ == "__main__":
    asyncio.run(main())

Другие вопросы по теме