【问题标题】:Clicking specific nested "a" tags when scraping with selenium?用硒刮擦时单击特定的嵌套“a”标签?
【发布时间】:2019-02-20 01:40:09
【问题描述】:

我正在尝试从该链接https://www.hopkinsguides.com/hopkins/index/Johns_Hopkins_ABX_Guide/Antibiotics 抓取信息

本站使用jquery。我的目标是刮掉所有的抗生素名称,然后为每个抗生素刮掉“非 FDA 批准的用途”,它包含在一个单独的链接中。我希望我说得通。

抗生素属于包含许多其他子类别的类别,这些子类别包含其余抗生素及其各自的链接。

我的程序第一次登录,点击前7个按钮展开并显示更多类别。我使用driver.find_element_by_x_path 扩展第一层,但我不能以相同的方式扩展第二层(通过循环通过 x_path),因为如果我这样做,最终会将我带到“非 FDA 批准使用”信息的另一个页面被包含而不是扩展页面。

这样做是因为一旦您展开第一层,那么第二层现在包含更多按钮/子类别和链接,可将您带到“非 FDA 批准使用”的页面。

所以如果这些是我的 x_paths

#//*[@id="firstul"]/li[1]/a 
#//*[@id="firstul"]/li[2]/a

li[1] 可能是一个重定向链接, li[2] 可以是一个显示更多链接的按钮(这是我首先想要的)

我做了一个汤来将按钮与链接分开,但现在我无法点击我在底部 for 循环中打印的“a”标签。

关于我应该如何处理的任何想法?提前致谢。

这是我的代码。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from random import randint
from bs4 import BeautifulSoup




#SIGN-IN
driver = webdriver.Chrome()
driver.get("http://www.hopkinsguide.com/home")
url = "https://www.hopkinsguides.com/hopkins/index/"

assert "Hopkins" in driver.title
sign_in_button = driver.find_element_by_xpath('//*[@id="logout"]')
sign_in_button.click()

user_elem = driver.find_element_by_name('username')
pass_elem = driver.find_element_by_id('dd-password')
user_elem.send_keys("user")
time.sleep(2)
pass_elem.send_keys("pass")
time.sleep(2)
sign_in_after_input = driver.find_element_by_xpath('//*[@id="dd-login-button"]')
sign_in_after_input.click()

def expand_page():    
    req = driver.get("https://www.hopkinsguides.com/hopkins/index/Johns_Hopkins_ABX_Guide/Antibiotics")
    time.sleep(randint(2, 4))
    #expand first layer
    for i in range(1, 8):
        driver.find_element_by_xpath("//*[@id='firstul']/li[" + str(i) + "]/a").click()
        time.sleep(2)

    html = driver.page_source
    soup = BeautifulSoup(html, features='lxml')
    for i in soup.find_all('a'):
        if i.get('data-path') != None:
            print(i)
            time.sleep(2)

expand_page()

【问题讨论】:

    标签: python selenium selenium-webdriver web-scraping


    【解决方案1】:

    为了扩展所有应该为您工作的值,这将扩展所有第一级值并通过递归检查元素的role 属性来继续检查是否有任何子值可扩展:

    def click_further(driver, elem):
        subs = WebDriverWait(driver, 5).until(lambda driver: elem.find_elements_by_xpath("./following-sibling::ul//li/a"))
        for sub in subs:
            if sub.get_attribute('role') == "button":
                sub.click()
                click_further(driver, sub)
    
    for idx in range(1,8):
        elem = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH, "//*[@id='firstul']/li[{}]/a".format(idx))))
        elem.click()
        click_further(driver, elem)
    

    我想你可以弄清楚如何获取要从中提取的文本。

    【讨论】:

    • 非常感谢。我运行它并收到此错误。我也找到了这个链接。 stackoverflow.com/questions/11908249/…>Aminoglycosides</a> is not clickable at point (311, 10). Other element would receive the click: <a href="https://www.hopkinsguides.com/hopkins/prime">...</a>
    • @Joelalexis,抱歉,我无法在我的 Windows/Ubuntu 上重现同样的错误,但您能否通过您分享的链接中建议的更改解决该问题?
    【解决方案2】:

    我想您想先展开所有可展开节点,然后再逐个访问底层链接。从我所看到的网站来看,区分属性是<li class="expandable index-expand"><li class="index-leaf">

    您可以使用 Selenium 定位“可扩展索引扩展”类,并首先单击嵌套的 <a> 标记。然后,每次单击时对展开的子图层重复相同的操作。一旦您不再在子层中检测到“可扩展索引扩展”类,您就可以继续从“索引叶”中获取链接。

    find_elements_by_class_name 应该可以解决问题

    【讨论】:

    • 嘿,非常感谢。好像你不能点击
    • 属性...可点击的标签是属性是<a role='button'>
  • @Joelalexis 是的,但是您可以使用它来定位嵌套的<a> 标签并单击它们。为了准确起见,让我更新我的答案:)
  • 猜你喜欢
    相关资源
    最近更新 更多
    热门标签