代码之家  ›  专栏  ›  技术社区  ›  SIM

无法从网页获取文本

  •  3
  • SIM  · 技术社区  · 6 年前

    我已经创建了一个脚本,使用Python和Selenium在下面的链接中获取所有可用的文本。这个网页已经激活了Lazyloading方法,这就是为什么每次滚动时都能看到更多的内容。我的脚本也能处理。

    然而,问题是,当我的脚本让网页到达底部耗尽其内容时,它就会在那里结巴。一旦它脱离循环,我就可以获取内容。我怎样才能跳出这个循环呢?

    我知道 .LoadingDots 总是在那里。这就是我找不到任何逻辑来打破循环的唯一原因。

    Link to that site

    这是我迄今为止所做的尝试:(无法摆脱循环)

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
    driver = webdriver.Chrome()
    wait = WebDriverWait(driver,10)
    driver.get("https://www.quora.com/topic/American-Football")
    
    while True:
    
        try:
            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, ".LoadingDots")))
        except Exception: break
    
    for item in wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".ui_qtext_rendered_qtext .ui_qtext_para"))):
        print(item.text)
    
    driver.quit()
    

    我知道如果我遵守以下规定,我可以解决问题:

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.common.exceptions import TimeoutException
    
    driver = webdriver.Chrome()
    wait = WebDriverWait(driver,10)
    driver.get("https://www.quora.com/topic/American-Football")
    
    last_len = len(wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".ui_qtext_rendered_qtext .ui_qtext_para"))))
    
    while True:
        for load_more in wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "a[id$='_more']"))):
            driver.execute_script("arguments[0].click();",load_more)
    
        try:
            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            wait.until(lambda driver: len(wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".ui_qtext_rendered_qtext .ui_qtext_para")))) > last_len)
            items = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".ui_qtext_rendered_qtext .ui_qtext_para")))
            last_len = len(items)
        except TimeoutException: break
    
    for item in items:
        print(item.text)
    
    driver.quit()
    

    我的问题是:我怎样才能用我第一个脚本使用的方法从那页中提取内容,用尽所有的滚动条 .加载点 ?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Guy    6 年前

    当页面滚动到按钮时,带有类的元素 .LoadingDots.regular 保持不变,但其父元素添加了新类 hidden . 您可以使用 get_attribute 功能。您也可以直接在类中找到它 spinner_display_area

    while True:
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    
        loading_dots = driver.find_element_by_class_name('spinner_display_area')
        if 'hidden' in loading_dots.get_attribute('class'):
            break;
    
        2
  •  0
  •   Andersson    6 年前

    您的脚本无法按预期工作,因为 (By.CSS_SELECTOR, ".LoadingDots") 选择器返回此元素 <div class="LoadingDots tiny"> 而且它是 总是隐藏 所以你对它的期望 隐形 总是返回 True 循环不能被破坏。

    你需要检查另一个元素 "LoadingDots" 类名: <div class="LoadingDots regular"> 逻辑如下:

    1. 向下滚动一页
    2. 等待加载点出现(开始加载更多内容)
    3. 等待加载点消失(加载更多内容完成)

    如果在翻页后,我们看不到点-打破循环

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
    driver = webdriver.Chrome()
    wait = WebDriverWait(driver, 5)
    driver.get("https://www.quora.com/topic/American-Football")
    
    while True:
        try:
            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".LoadingDots.regular")))
            wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, ".LoadingDots.regular")))
        except Exception: continue
        else: break
    
    for item in wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".ui_qtext_rendered_qtext .ui_qtext_para"))):
        print(item.text)
    
    driver.quit()
    

    但是!请注意,我发布这个脚本只是为了指出您的脚本不工作的原因…它不是很有效,因为如果内容加载太快(可能性很低,但是…)脚本可能无法捕捉到加载点出现的时刻,您将无法获得所有必需的内容。

    所以@guy解决方案似乎更可靠(+1)