首页 > 解决方案 > 如何创建面向对象的代码来替换 python 中的许多“尝试”循环

问题描述

我正在重复此代码,以便我可以从网站上抓取一些新闻。周末和节假日,网站不刷新,只有工作日的消息。

这是我为获取前一个工作日新闻的代码创建的解决方案,但我知道它不是正确的编程方式。

import smtplib, ssl
import datetime, time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException,StaleElementReferenceException, ElementClickInterceptedException

options = webdriver.ChromeOptions()
#options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 10)
driver.get('https://fiis.com.br/atualizacoes/')
driver.implicitly_wait(10)
time.sleep(2)

#here I try to close a new html popup that has been there since last week

try:
    driver.find_element_by_xpath('/html/body/div[1]/div/button').click()
except NoSuchElementException:
    print("NoSuchElementException")
    try:
        driver.find_element_by_xpath('/html/body/div[2]/div/button').click()
    except NoSuchElementException:
        print("NoSuchElementException")
except ElementClickInterceptedException:
    try:
        driver.find_element_by_xpath('/html/body/div[2]/div/button').click()
    except NoSuchElementException:
        print("NoSuchElementException")


wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '[data-type="date"]'))).click()

#here I try diferent dates, first a today minus 1, then today minus 2 ... until today minus 4

try:
    today = datetime.date.today()
    five_day = datetime.timedelta(days=-1)
    d_N1 = today + five_day
    d_N1_2 = d_N1.strftime('%Y-%m-%d')
    d_N1_3 = d_N1.strftime('%d.%m.%Y')

    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, f'li[data-item="{d_N1_2}"]')))
    driver.find_element_by_css_selector(f'li[data-item="{d_N1_2}"]').click()
except TimeoutException or NoSuchElementException:
    try:
        today = datetime.date.today()
        five_day = datetime.timedelta(days=-2)
        d_N1 = today + five_day
        d_N1_2 = d_N1.strftime('%Y-%m-%d')
        d_N1_3 = d_N1.strftime('%d.%m.%Y')

        wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, f'li[data-item="{d_N1_2}"]')))
        driver.find_element_by_css_selector(f'li[data-item="{d_N1_2}"]').click()
    except TimeoutException or NoSuchElementException:
        try:
            today = datetime.date.today()
            five_day = datetime.timedelta(days=-3)
            d_N1 = today + five_day
            d_N1_2 = d_N1.strftime('%Y-%m-%d')
            d_N1_3 = d_N1.strftime('%d.%m.%Y')

            wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, f'li[data-item="{d_N1_2}"]')))
            driver.find_element_by_css_selector(f'li[data-item="{d_N1_2}"]').click()
        except TimeoutException or NoSuchElementException:
            try:
                today = datetime.date.today()
                five_day = datetime.timedelta(days=-3)
                d_N1 = today + five_day
                d_N1_2 = d_N1.strftime('%Y-%m-%d')
                d_N1_3 = d_N1.strftime('%d.%m.%Y')

                wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, f'li[data-item="{d_N1_2}"]')))
                driver.find_element_by_css_selector(f'li[data-item="{d_N1_2}"]').click()
            except TimeoutException or NoSuchElementException:
                driver.close()
                driver.quit()

如果昨天的消息是avaiable,我不需要得到前一天。

未来4天不够,所以可以考虑一个更好的解决方案。

标签: python

解决方案


你可以用这个替换try-blocks:

days_ago = -4
today = datetime.date.today()
for n in range(-1, days_ago-1, -1):
    five_day = datetime.timedelta(days=n)
    d_N1 = today + five_day
    d_N1_2 = d_N1.strftime('%Y-%m-%d')
    d_N1_3 = d_N1.strftime('%d.%m.%Y')
    try:
        wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, f'li[data-item="{d_N1_2}"]')))
        driver.find_element_by_css_selector(f'li[data-item="{d_N1_2}"]').click()
        break
    except TimeoutException, NoSuchElementException:
        if n <= days_ago:
            print(f"failed to fetch data for any date")

这是通过使用一个循环来工作的,该循环将运行n=-1, n=-2, n=-3, n=-4并继续,直到所有n值都用完,或者直到driver.find_element_by_css_selector不产生异常(这是break可以到达语句的唯一方法)。


推荐阅读