【问题标题】:Implementing a modified do-while loop in Python i.e. do at least once and another time at the end of the loop?在 Python 中实现修改后的 do-while 循环,即在循环结束时至少执行一次和另一次?
【发布时间】:2016-09-03 18:41:31
【问题描述】:

我在实现等同于 do while 循环的东西时遇到问题。

问题描述

我正在抓取一个网站,结果页面是分页的,即

1, 2, 3, 4, 5, .... NEXT

我正在使用NEXT 链接存在的测试条件遍历页面。如果有一个结果页面,则没有NEXT 链接,所以我将只抓取第一页。如果有多个页面,最后一页也没有NEXT 链接。所以刮板功能也适用于该页面。抓取功能调用findRecords()

所以我隔离我的NEXT 链接使用:

next_link = driver.find_element(By.XPATH, "//a[contains(text(),'Next')][@style='text-decoration:underline; cursor: pointer;']")

所以我想运行一个至少执行一次抓取的循环(当有一个或多个结果页面时)。我还使用 click() 函数单击了NEXT 按钮。我到目前为止的代码是:

while True:
    findRecords()
    next_link = driver.find_element(By.XPATH, "//a[contains(text(),'Next')][@style='text-decoration:underline; cursor: pointer;']")
    if not next_link:
        break
    next_link.click()

这不起作用。好吧,它可以工作并且会刮擦,但是当它到达最后一页时,它会给我一个NoSuchElementException,如下所示:

Traceback(最近一次调用最后一次): 文件“try.py”,第 47 行,在 next_link = driver.find_element(By.XPATH, "//a[contains(text(),'Next')][@style='text-decoration:underline; cursor: pointer;']") 文件“/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py”,第 752 行,在 find_element '价值':价值})['价值'] 文件“/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py”,第236行,在执行 self.error_handler.check_response(响应) 文件“/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/errorhandler.py”,第 192 行,在 check_response 引发异常类(消息、屏幕、堆栈跟踪) selenium.common.exceptions.NoSuchElementException:消息:没有这样的元素:无法找到元素:{"method":"xpath","selector":"//a[contains(text(),'Next')][@样式='文本装饰:下划线;光标:指针;']"} (会话信息:chrome=53.0.2785.89) (驱动信息:chromedriver=2.20.353124 (035346203162d32c80f1dce587c8154a1efa0c3b),platform=Linux 3.13.0-92-generic x86_64)

我知道该元素在最后一页上确实不存在,因为就像我之前所说的,NEXT 元素在最后一页上不存在。

那么我该如何修复我的 while 循环,以便能够在条件不成立时抓取单个页面结果和/或最后一页,并且还优雅地跳出 while 循环而不给我那个可怕的错误?

PS:除了上面的while循环,我还尝试了以下方法:

is_continue = True
while is_continue:
    findRecords()
    next_link = driver.find_element(By.XPATH, "//a[contains(text(),'Next')][@style='text-decoration:underline; cursor: pointer;']")
    if next_link:
        is_continue = True
        next_link.click()
    else:
        is_continue = False 

如果有帮助,这里也是我的刮板功能findRecords()

def findRecords():
    filename = "sam_" + letter + ".csv"
    bsObj = BeautifulSoup(driver.page_source, "html.parser")
    tableList = bsObj.find_all("table", {"class":"width100 menu_header_top_emr"}) 
    tdList = bsObj.find_all("td", {"class":"menu_header width100"})

    for table,td in zip(tableList,tdList):
            a = table.find_all("span", {"class":"results_body_text"})
            b = td.find_all("span", {"class":"results_body_text"})
            with open(filename, "a") as csv_file:
                csv_file.write(', '.join(tag.get_text().strip() for tag in a+b) +'\n')

【问题讨论】:

  • 修正缩进,向我们展示完整的堆栈跟踪。
  • @user2357112 我已经修复了两者以匹配我所拥有的。

标签: python loops selenium for-loop while-loop


【解决方案1】:

当您搜索下一个链接时,将代码更改为 find_elements,如果 Next 存在则返回大小为 1 的列表,否则返回大小为 0 的列表,但也不例外。

next_link = driver.find_elements(By.XPATH, "//a[contains(text(),'Next')][@style='text-decoration:underline; cursor: pointer;']")

您现在需要设置逻辑来访问此列表中的下一个 web 元素。

【讨论】:

    【解决方案2】:

    您应该尝试使用find_elements,它会返回 WebElement 列表或空列表。所以只需检查它的长度如下:-

    while True:
        findRecords()
        next_link = driver.find_elements(By.XPATH, "//a[contains(text(),'Next')][@style='text-decoration:underline; cursor: pointer;']")
        if len(next_link) == 0:
            break
        next_link[0].click()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-06
      • 1970-01-01
      • 2023-04-02
      • 2011-09-21
      • 2022-01-16
      相关资源
      最近更新 更多