bs4 не находит элементы по классам и атрибутам

Решаю стандартную задачку для python-библиотек bs4 и requests - открытие первых результатов запроса в отдельных вкладках. На вход подаются: количество новых вкладок и критерии поиска, которые я извлекаю из аргументов командной строки и добавляю к запросу на гугл. Само собой проверяю на ошибки запрос.

import sys
import requests
import webbrowser
import bs4

try:
    count_links = int(sys.argv[1])
except ValueError:
    print('Неправильно введено количество вкладок')
    sys.exit(-1)
print('Гуглим, гуглим...')
res = requests.get('http://google.com/search',
                   {'q': ' '.join(sys.argv[2:])})
res.raise_for_status()

В ответ я получаю HTML-документ и далее парсю его с помощью bs4.

soup = bs4.BeautifulSoup(res.text, features='html.parser')

Далее нужно найти элементы в этом документе, которые содержат ссылку на соответствующий результат поиска. Инспектируя страничку, я обнаружил, что каждый результат поиска храниться в контейнере <div class="g">, а если еще конкретнее, то в элементе <a>, который имеет атрибут rel="noreferrer noopener" введите сюда описание изображения

При попытке поиска данного элемента с помощью css-селектора links = soup.select('a[rel="noreferrer noopener"]') и links = soup.select('.g') получаю пустоту. Также пробовал найти элементы с помощью links = soup.find_all('div', class_='g') в ответ на что я тоже получаю пустоту. Поиск с помощью soup.find_all("a", attrs={"rel": "noreferrer noopener"}) тоже не увенчался успехом((

Помогите, что может быть не так в данном коде. Может я конечно чего-то не замечаю(


Ответы (1 шт):

Автор решения: Pain Worsnop

Данные на сайте могут генерироваться динамически при помощи javascript. В таком случае спарсить эти данные силами requests+bs4 не удастся. Дело в том, что bs4 парсит исходный код страницы, не исполняя js. Для исполнения js кода и получения страницы, идентичной той, которую мы видим в браузере, можно использовать selenium web driver - это набор драйверов для различных браузеров, снабжающийся библиотеками для работы с этими драйверами.

from selenium import webdriver
from bs4 import BeautifulSoup

ops = webdriver.ChromeOptions()
ops.add_argument('headless')
driver = webdriver.Chrome("chromedriver.exe", options=ops)

url = 'http://google.com/search?q=yandex'
driver.get(url)
html = driver.page_source

parse = BeautifulSoup(html, features="html.parser")
for tag in parse.find_all("a"):
    if tag.has_attr('href'):
        print(tag['href'])
→ Ссылка