无法从网页获取文字

时间:2018-11-28 15:05:04

标签: python python-3.x selenium selenium-webdriver web-scraping

我已经使用python和selenium创建了一个脚本,以在下面的链接中获取所有可用的文本。该网页已启用了惰性加载方法,这就是为什么每次滚动时都可以看到更多内容的原因。我的脚本也可以处理。

但是,问题是当我的脚本使网页到达底部时耗尽了其内容时,它卡在了那里。一旦可以打破循环,我就可以获取内容。我该如何跳出循环?

我知道.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()

我的问题是:我该如何使用我使用.LoadingDots的第一个脚本尝试的方式从该页面中耗尽所有滚动的内容?

2 个答案:

答案 0 :(得分:2)

将页面滚动到按钮时,具有类.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;

答案 1 :(得分:0)

您的脚本无法按预期运行,因为(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)