Выбор элементов по xpath - PullRequest
0 голосов
/ 15 января 2020

У меня есть эта страница https://www.punters.com.au/form-guide/2020-01-14/

Есть такие названия рас, как Spendthrift Australia Park, Dalby и др. c. Я хотел бы найти способ извлечь гонки для определенной страны. Например, мой сценарий должен проходить гонки в Австралии. Но я не знаю, как сделать правильный путь к этим гонкам. Потому что количество гонок каждый раз разное. Или для любой другой страны. Мне просто нужен правильный xpath

from selenium import webdriver

country = input('Enter country name (ex Australia, New Zealand..): ')
driver = webdriver.Chrome()
driver.get("https://www.punters.com.au/form-guide/2020-01-14/")
for i in driver.find_elements_by_xpath("//tr[./td/img[@title='Australia']]//following-sibling::tr/td[@class='upcoming-race__td upcoming-race__meeting-name upcoming-races__show-pdfs']//following-sibling::td[1]/a".format(country)):
    print(i.text)

driver.close()

Ответы [ 2 ]

1 голос
/ 15 января 2020

Если вы хотите выбрать целевые узлы одним «волхвом c xpath», вот оно:

from selenium import webdriver

country = 'South Africa'
driver = webdriver.Chrome()
driver.get("https://www.punters.com.au/form-guide/2020-01-14/")

xpath = f"//tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='{country}']][position()<=(count(//tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='{country}']])-count(//tr[preceding-sibling::tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='{country}'] and contains(@class, 'upcoming-race__row--country')][1]])-count(//tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='{country}'] and contains(@class, 'upcoming-race__row--country')][1]))]/td[1]"
found_nodes = driver.find_elements_by_xpath(xpath)

driver.close()

Давайте опишем, что делает этот XPath на примере Новой Зеландии :

Я сделаю псевдонимы блоков XPath для лучшей читаемости концепции результата в конце.

1. Первый часть о поиске с чего начать - давайте найдем узел с новозеландским заголовком (давайте назовем его TARGET_XPATH) :

`//tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='New Zealand']]`

2. Теперь нам нужно ограничить найденные результаты только одной страной. Лучший выбор для этой операции в текущем случае, я знаю, - оператор «позиция». Мы должны предоставить позицию последнего полезного элемента (перед первым "trashy") в наших результатах. Давайте вычислим это:

`(count(//tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='New Zealand']])-count(//tr[preceding-sibling::tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='New Zealand'] and contains(@class, 'upcoming-race__row--country')][1]])-count(//tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='New Zealand'] and contains(@class, 'upcoming-race__row--country')][1]))`

Здесь мы считаем три типа элементов:

a. Количество узлов после заголовка нашей страны (с именем COUNT_TOTALS) :

count(//tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='New Zealand']])

b. Количество узлов после первого «мусорного» узла (с именем COUNT_AFTER_TRASHY_HEADER) :

count(//tr[preceding-sibling::tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='New Zealand'] and contains(@class, 'upcoming-race__row--country')][1]])

c. И мы должны проверить наличие любого «мусорного» узла, в случае, когда мы ищем расы для последней страны в таблице - у него не будет следующего «мусорного» узла (с именем COUNT_TRASHY_HEADER) :

count(//tr[preceding-sibling::tr[contains(@class, 'upcoming-race__row--country')]/td/img[@title='New Zealand'] and contains(@class, 'upcoming-race__row--country')][1])

3. Используйте наш счетчик в качестве фильтра:

TARGET_XPATH[position()<=(COUNT_TOTALS - COUNT_AFTER_TRASHY_HEADER - COUNT_TRASHY_HEADER)]
0 голосов
/ 15 января 2020

Давайте попробуем это так (только для Австралии):

from selenium import webdriver
import pandas as pd

driver = webdriver.Chrome()
driver.get("https://www.punters.com.au/form-guide/2020-01-14/")

tabs = driver.find_elements_by_xpath('//table')
rows = []
for i in tabs[0].find_elements_by_xpath("//tr[./td/img[@title='Australia']]/following-sibling::tr[position()<5]"):
    row = []
    for dat in i.find_elements_by_xpath('.//td'):        
        row.append(dat.text)
    rows.append(row)
pd.DataFrame(rows)

Вывод (простите за форматирование):

             0  1   2   3   4   5   6   7   8   9   10
0   Spendthrift Australia Park  ABD ABD ABD ABD ABD ABD ABD ABD     
1   Dalby   6,2 3,2 8,9,4   8,4,7   10,5,1  ABD 8,9,6   3,6,4   11,9,1  6,1,5
2   Corowa  3,1,4   6,4,3   2,4 2,1,5   2,7,9   12,2,6  3,1,6           
3   Scone   14,9,6  10,1,18 5,3,1   7,2,6   12,6,8  12,2,10 12,7,2      
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...