Я столкнулся с проблемой при очистке заголовков новостей, субтитров и ссылок с веб-сайта The Sun Football с помощью Selenium. Несмотря на, казалось бы, правильную реализацию XPath для выбора нужных элементов (div[@class = "teaser__copy-container"] для контейнеров, span[@class = "teaser__headline teaser__kicker t-p-color"] для заголовков и h3[@class = "teaser__subdeck"] для субтитров), я последовательно извлекаю одни и те же данные для всех новостей.
Фрагмент кода
from selenium import webdriver
from selenium.webdriver.firefox.service import Service # Using Firefox service
import pandas as pd
# Website URL for news scraping
website = "https://www.thesun.co.uk/sport/football/"
# Path to the GeckoDriver executable
path = "/Users/dada/AutomationProjects/drivers/geckodriver.exe"
# Configure Firefox service with GeckoDriver path
service = Service(executable_path=path)
# Initialise Firefox WebDriver using the service
driver = webdriver.Firefox(service=service)
# Open the desired website
driver.get(website)
containers = driver.find_elements(by = "xpath", value='//div[@class = "teaser__copy-container"]')
titles = []
subtitles = []
links = []
for container in containers:
title = container.find_element(by = "xpath", value='//div[@class = "teaser__copy-container"]/a/span[@class = "teaser__headline teaser__kicker t-p-color"]').get_attribute("data-original-text")
subtitle = container.find_element(by = "xpath", value='//div[@class = "teaser__copy-container"]/a/h3[@class = "teaser__subdeck"]').get_attribute("data-original-text")
link = container.find_element(by = "xpath", value='//div[@class = "teaser__copy-container"]/a').get_attribute("href")
titles.append(title)
subtitles.append(subtitle)
links.append(link)
dict = {'Titles' : titles, 'Subtitles' : subtitles, 'Links' : links}
headlines_df = pd.DataFrame(dict)
print(headlines_df)
Проверенные XPath: я дважды проверил XPath с помощью инструментов разработчика браузера, чтобы убедиться, что они точно нацелены на нужные элементы. Проблема сохраняется. Я по-прежнему извлекаю те же заголовки, субтитры и ссылки, несмотря на этап устранения неполадок.
Версия селена: 4.19.0 | Версия Python: 3.9.19 | Окружающая среда: блокнот Jupyter.
Я буду признателен за любую информацию или предложения, которые помогут мне определить основную причину этой проблемы и успешно скопировать отдельные заголовки, субтитры и ссылки с веб-сайта The Sun Football.






Да... есть одна "странная" вещь, которую приходится делать с XPath при поиске по существующему элементу. Вместо
link = container.find_element(By.XPATH, '//div[@class = "teaser__copy-container"]/a')
вам нужно добавить '.' к началу XPath, например.
link = container.find_element(By.XPATH, './/div[@class = "teaser__copy-container"]/a')
^ period added here
Это применимо только к XPath и только тогда, когда вы используете .find_element() из элемента. Например, driver.find_element() работает нормально, но element.find_element() требует '.'. Это должно решить ваши проблемы.
Оказывается, ваши локаторы названия и т. д. были неправильными. Я обновил и упростил их. Полный рабочий код приведен ниже.
from selenium import webdriver
from selenium.webdriver.common.by import By
import pandas as pd
# Website URL for news scraping
website = "https://www.thesun.co.uk/sport/football/"
# Initialise Firefox WebDriver using the service
driver = webdriver.Firefox()
driver.maximize_window()
# Open the desired website
driver.get(website)
containers = driver.find_elements(By.XPATH, '//div[@class = "teaser__copy-container"][./a]')
titles = []
subtitles = []
links = []
for container in containers:
title = container.find_element(By.CSS_SELECTOR, 'a > span').get_attribute("data-original-text")
subtitle = container.find_element(By.CSS_SELECTOR, 'a > h3').get_attribute("data-original-text")
link = container.find_element(By.CSS_SELECTOR, 'a').get_attribute("href")
titles.append(title)
subtitles.append(subtitle)
links.append(link)
dict = {'Titles' : titles, 'Subtitles' : subtitles, 'Links' : links}
headlines_df = pd.DataFrame(dict)
print(headlines_df)
Это выводит
Titles Subtitles Links
0 OF HIS ILK Gundogan's glam wife enters row with Barca st... https://www.thesun.co.uk/sport/27404398/ilkay-...
1 NICE TUCH Bayern president hails Tuchel for 'tactical m... https://www.thesun.co.uk/sport/27402309/bayern...
...
Дополнительный отзыв
Начиная с Selenium 4.6 вам больше не нужно загружать, настраивать и поддерживать собственные драйверы. Был добавлен Selenium Manager, который автоматически загрузит и установит для вас драйверы, соответствующие установленному вами браузеру. Итак, ваш первоначальный код можно упростить до
from selenium import webdriver
website = "https://www.thesun.co.uk/sport/football/"
driver = webdriver.Firefox()
driver.get(website)
Предпочтительный способ написать .find_element() звонок:
from selenium.webdriver.common.by import By
driver.find_element(By.XPATH, '//div[@class = "teaser__copy-container"]/a')
Ваш способ будет работать, но он подвержен опечаткам, и ваша IDE не узнает об опечатках, пока вы не запустите сценарий и он не завершится неудачно. Использование By.XPATH и т. д. позволяет избежать опечаток в типе локатора, а ваша IDE поможет вам автоматически заполнить его. Если есть опечатки, IDE пометит их как ошибки перед запуском, что сэкономит ваше время.
Поскольку вы запросили XPath, элементы containers уже найдены с помощью XPath. Приведенный ниже код должен позаботиться обо всем остальном.
title = container.find_element(By.XPATH, './a/span').get_attribute("data-original-text")
subtitle = container.find_element(By.XPATH, './a/h3').get_attribute("data-original-text")
link = container.find_element(By.XPATH, './a').get_attribute("href")
@DarryMich Оказывается, ваши локаторы были неверными. Я обновил и упростил их. Я также опубликовал полный код с обновлениями и изменениями на основе моих дополнительных отзывов. Код работает, и я также опубликовал фрагмент вывода.
Вы заметите, насколько проще синтаксис селекторов CSS и насколько проще их использовать в случае element.find_element() и т. д. Это лишь одна из многих причин, по которым селекторам CSS следует отдавать предпочтение перед XPath. XPaths имеет свое место, но он предназначен для: 1. поиска элементов по содержащемуся в них тексту и 2. выполнения сложного обхода DOM.
Спасибо, JeffC, за ценные советы по решению проблемы, с которой я столкнулся. Предоставленный вами код работает, и синтаксис селектора CSS намного проще и проще. Я искренне ценю время и усилия, которые вы вложили в мою помощь! Но если вы не возражаете, мне интересно узнать правильные локаторы XPATH.
Сделанный. Добавил их в конец вопроса.
После добавления точки "." Я получил сообщение об ошибке: NoSuchElementException: Сообщение: Невозможно найти элемент: .//div[@class = "teaser__copy-container"]/a/span[@class = "teaser__headline teaser__kicker t-p-color"]; Документацию по этой ошибке можно найти по адресу: selenium.dev/documentation/webdriver/troubleshooting/…. Когда снимаю, проблема сохраняется - извлекаются одни и те же заголовки, субтитры и ссылки.