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 шт):
Данные на сайте могут генерироваться динамически при помощи 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'])