#python #selenium #xpath #web-scraping #webdriverwait
#python #selenium #xpath #веб-очистка #webdriverwait
Вопрос:
Я пытаюсь очистить данные с этого веб-сайта.
Более конкретно, я хочу, чтобы мой скрипт подсчитывал количество строк в таблице и извлекал номер посещаемости из каждой строки (см. Изображение, прикрепленное ниже).
Просматривая веб-сайт, я вижу следующее для даты в первой строке (1 декабря):
<td ng-repeat="(k,h) in sec.headers track by $index" class="date ng-scope" data-high="false" data-hidden="false"
ng-style="{'text-align':h.properties.align}" ng-bind-html="vals | getColData:[k]:language:seasonId"
compile-table-col="" style="text-align: left;"><span>Dec. 1</span></td>
Затем я вижу блок кода для подсчета количества пользователей в первой строке (872)
<td ng-repeat="(k,h) in sec.headers track by $index" class="attendance ng-scope" data-high="false"
data-hidden="false" ng-style="{'text-align':h.properties.align}" ng-bind-html="vals | getColData:[k]:language:seasonId"
compile-table-col="" style="text-align: right;"><span>872</span></td>
Я пробовал несколько версий driver.find_elements_by_class_name
, таких как
elements = driver.find_elements_by_class_name("date ng-scope")
и
driver.find_elements_by_xpath("//td[@class='date ng-scope']")))
К сожалению, ни одно из них не сработало.
Может ли кто-нибудь указать мне правильное направление? Если бы кто-нибудь мог дать совет о том, как правильно подсчитать количество строк, подсчитав количество экземпляров 'date ng-scope'
и извлекая соответствующие подсчеты толпы.
Комментарии:
1. Вам на 100% нужно, чтобы все было сделано в selenium? BeautifulSoup или даже pandas_html может быть проще.
2. @CeliusStingher Нет, но меня как бы подтолкнули к использованию Selenium, потому что мне нужно было выбирать параметры в выпадающих меню и нажимать кнопки. Я бы хотел использовать BeautifulSoup, но мне нужно было бы иметь возможность обновлять адрес после выбора соответствующих пунктов выпадающего меню.
Ответ №1:
Поскольку это таблица, ее довольно легко достичь, так как все, что вам нужно делать, это постоянно увеличивать значение таблицы на 1. Вот как я это сделал:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep, strftime
url = "https://www.ushl.com/view#/schedule/24/67/12/home?league=1amp;gametype=-1"
webdriver = webdriver.Chrome()
webdriver.get(url)
x = 0
i = 2
while x == 0:
try:
date = webdriver.find_element_by_xpath(f"/html/body/div[5]/div[1]/div[4]/div[2]/div[1]/div/div[3]/div/div/div/div/div/div/ng-view/div[2]/div[3]/div[1]/table/tbody/tr[{i}]/td[1]/span").text
attendance = webdriver.find_elements_by_xpath(f"/html/body/div[5]/div[1]/div[4]/div[2]/div[1]/div/div[3]/div/div/div/div/div/div/ng-view/div[2]/div[3]/div[1]/table/tbody/tr[{i}]/td[8]/span")[0].text
print(f"Attendance Of {attendance} On Date {date}")
i = 1
except:
x = 1
break
Позвольте мне объяснить:
Строка 1-3 импортирует необходимые модули, такие как selenium.
Строка 4 устанавливает URL в строку.
Строка 5 определяет webdriver как Chrome.
Строка 6 использует Chrome для открытия URL-адреса, который мы определили ранее.
Строка 7 определяет x как 0. Позже нам нужно, чтобы x было равно 0 для цикла while.
Строка 8 определяет i как 2, который нам понадобится для таблицы позже.
Строка 9 инициирует цикл while, который будет выполняться до тех пор, пока x равно 0, значение которого мы установили ранее.
Строка 10 запускает команду try . Позже вы поймете, зачем нам это нужно.
Строка 11 устанавливает дату в текст переменной xpath. Я уже использовал html раньше и поэтому примерно знаю, как работает табличная система. tr означает строку таблицы. Первая дата, 1 декабря, — это строка таблицы 2. Ранее мы установили i равным 2, поэтому мы можем использовать tr[{i}] для представления 2 .
Строка 12 делает то же самое, но для посещаемости, по-прежнему используя i, поскольку это таблица. Я добавил [0] в конце, потому что xpath для посещаемости был списком. Хотя я почти уверен, что списка нет, selenium все равно так думал, поэтому я решил использовать [0] для получения первого элемента списка. Нет второго или третьего элемента, поэтому [1] или [2] не будут работать.
Строка 13 выводит информацию для пользователя. Строка 14 увеличивает i на 1, потому что в следующем цикле нам нужно получить доступ к 3-й строке таблицы, поэтому i = 1 устанавливает i равным 3.
Мы продолжаем выполнять это до тех пор, пока не останется больше строк таблицы. Когда это происходит, мы используем команду try в строке 15, чтобы прервать цикл while.
Комментарии:
1. Спасибо. это действительно работает, но не могли бы вы объяснить синтаксис и мыслительный процесс? особенно за div[i] . Мне трудно понять, что происходит.
2. Я надеюсь, что это поможет
3. Я думаю, что я почти на месте. В основном мне было трудно понять, как вы получили все эти div [i], и я вижу, что вы «скопировали полный Xpath». Однако, как вы узнали, что вам нужно добавить
/span
в обе строки? Кроме того, вы сказали, что знали, что вам нужно добавить[0]
для посещаемости, потому что xpath для attendendance — это список. Не могли бы вы подробнее остановиться на этом? Я попробовал[1]
или разные числа, чтобы посмотреть, что я получу, и я узнал, что[0]
это приводит только к тому, что что-либо печатается.4. Извините, я понял, что я делал «копировать полный Xpath» на одну строку выше, где я должен был. Я до сих пор не понимаю, откуда вы знаете, что вы должны были
[0].
указать, что я даже не могуattendance = webdriver.find_elements_by_xpath(f"/html/body/div[5]/div[1]/div[4]/div[2]/div[1]/div/div[3]/div/div/div/div/div/div/ng view/div[2]/div[3]/div[1]/table/tbody/tr[{i}]/td[8]/span").text
распечатать, чтобы увидеть, что это список, я бы не догадался о решении.5. Это помогает?
Ответ №2:
Таблицы — это очень весело. Я считаю, что лучше всего выполнять детализацию извне, а не переходить сразу к нужному элементу. Например, количество строк.
driver.findElements("//div[contains(@class,'table-container')]//tr")
вернет список элементов, а при получении размера этого списка вы получите количество строк (сюда входит строка заголовка, поэтому, если вы хотите, чтобы фактическое количество игр вычло 1). Переведенное выражение xpath выглядит следующим образом: «найдите любой элемент div, где имя класса содержит строку «table-container» и ниже по потоку любые элементы tr»
Поле посещаемости можно найти с помощью этого xpath:
//div[contains(@class,'table-container')]//tr[2]/td[contains(@class,'attendance')]/span
где tr[2] означает вторую строку. Программно сделайте это «[2]» переменной и замените индекс цикла на 2 и выполните итерацию по количеству строк.
Ответ №3:
Используйте WebDriverWait()
и ждите visibility_of_all_elements_located()
и используйте следующее css selector
, чтобы определить количество строк, а затем выполнить итерацию и найти соответствующие столбцы.
driver.get("https://www.ushl.com/view#/schedule/24/67/12/home?league=1amp;gametype=-1")
totalnoofrows=WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, ".resp >.ht-table >tbody >tr")))
for row in totalnoofrows[1:]:
print("Date :" row.find_element_by_xpath("./td[1]").text)
print("Crowd :" row.find_element_by_xpath("./td[8]").text)
print("==============================================")
Вам необходимо импортировать следующие библиотеки.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Вывод на консоль:
Date :Dec. 1
Crowd :872
==============================================
Date :Dec. 14
Crowd :816
==============================================
Date :Dec. 15
Crowd :1065
==============================================
Date :Dec. 16
Crowd :497
=============================================