【问题标题】:Selecting elements by xpath通过 xpath 选择元素
【发布时间】:2020-01-15 13:13:30
【问题描述】:

我有这个页面 https://www.punters.com.au/form-guide/2020-01-14/

有诸如 Spendthrift Australia Park、Dalby 等赛事名称。 我想找到一种方法来提取某些国家的种族。例如,我的剧本应该在澳大利亚参加比赛。但我不知道如何为那些比赛制作正确的 xpath。因为每次比赛的次数都不一样。 或者对于任何其他国家。 我只需要正确的 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()

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 好吧,我尝试使用 xpath 选择两个兄弟标签之间的数据。包子不成功,最后一个也不行。因为最后有不同的div。 @JackFleeting
  • 您应该编辑您的问题并发布您尝试过的内容;否则,有些人可能会投票结束您的问题。
  • 我添加了一些硒代码,所以很容易看到@JackFleeting
  • 如你所见,我有所有 10 个网址,我只想要澳大利亚下的网址。

标签: python xpath web-scraping


【解决方案1】:

如果你想用一个“magic 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. 现在我们需要将找到的结果限制在单个国家/地区。 在我知道的当前情况下,此操作的最佳选择 - “位置”运算符。 我们必须在结果中提供最后一个有用元素的位置(在第一个“垃圾”之前)。让我们计算一下:

`(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]))`

这里我们统计了三种元素:

一个。我们国家头节点之后的节点数(命名为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)]

【讨论】:

  • 嗯,非常感谢。这是一个巨大的 xpath,可能还有其他方法,但你证明了这可以通过这种方式完成。干得好!
【解决方案2】:

让我们试试这个方法(仅适用于澳大利亚):

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      

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-07
    • 1970-01-01
    • 2016-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 2021-11-21
    相关资源
    最近更新 更多