【问题标题】:Python for loop skips iterationPython for 循环跳过迭代
【发布时间】:2021-08-23 11:17:57
【问题描述】:

所以我制作了一个 selenium 机器人,它遍历区域代码列表并将此代码发送到网站的搜索框,该网站将代码更改为城市名称,然后我抓取该名称以获得城市列表代替代码列表。问题是,当我的 for 循环遍历列表时,有时它会“跳过”给定的命令并直接进入下一次迭代,因此我没有收到完整的城市列表。列表中的某些代码不存在或不适合传入网站,因此我对这种情况进行了例外处理。

import time
import pandas
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

chrome_driver_path = "D:\Development\chromedriver.exe"
driver = webdriver.Chrome(chrome_driver_path)
driver.get("https://eteryt.stat.gov.pl/eTeryt/rejestr_teryt/udostepnianie_danych/baza_teryt/uzytkownicy_indywidualni/wyszukiwanie/wyszukiwanie.aspx?contrast=default")

# Get the column with the codes from excel sheet and redo it into the list.
data = pandas.read_excel(r"D:\NFZ\FINAL Baza2WUJEK(poprawione1)-plusostatniepoprawki.xlsx")
codes = data["Kody terytorialne"].tolist()


cities = []


iteration = 0

for code in codes:
    time.sleep(0.05)
    iteration += 1
    print(iteration)
    if code == "Absence":
        cities.append("Absence")
    elif code == "Error":
        cities.append("Error")
    elif code == 2211041 or code == 2211021:
        cities.append("Manual")
    else:
        # Send territorial code
        driver.find_element_by_xpath('//*[@id="body_TabContainer1_TabPanel1_TBJPTIdentyfikator"]').clear()
        driver.find_element_by_xpath('//*[@id="body_TabContainer1_TabPanel1_TBJPTIdentyfikator"]').send_keys(code)
        # Search
        try:
            button = WebDriverWait(driver, 20).until(
                EC.presence_of_element_located((By.XPATH,
                                                '/html/body/form/section/div/div[2]/div[2]/div/div[2]/div/div[2]/div[1]/div[2]/div[1]/div/input')))
            button.click()
        except:
            button = WebDriverWait(driver, 20).until(
                EC.presence_of_element_located((By.XPATH,
                                                '/html/body/form/section/div/div[2]/div[2]/div/div[2]/div/div[2]/div[1]/div[2]/div[1]/div/input')))
            button.click()
        # Scrape city name
        city = WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="body_TabContainer1_TabPanel1_GVTERC"]/tbody/tr[2]/td[1]/strong'))).text.split()
        print(code)
        print(city)
        cities.append(city)


table = {
    "Cities": cities
}

df = pandas.DataFrame.from_dict(table)
df.to_excel("cities-FINAL.xlsx")
driver.close()

这是我的控制台日志的一部分。如您所见,在指示迭代次数为 98 之后,它会跳到 99 处,它完全可以正常工作,打印城市和地区代码。这个问题发生在循环的更深处,但每次它从第 98 次迭代开始。与此相关的领土代码不是例外之一。

96 <-- Iteration
2201025 <-- Territorial Code
['Kędzierzyn-Koźle', '(2201025)'] <-- City Name
97
2262011
['Bytów', '(2262011)']
98 !<-- Just iteration!
99
2205084
['Gdynia', '(2208011)']

**!Quick Note due to the answers! Here is the order of the print statements in the console. First: number of the iteration, Second: Territorial Code related to the iteration, Third: City Name**

【问题讨论】:

  • codes[97]的值是多少?
  • 是的,必须触发顶部的 code 检查之一,这会导致其余打印被跳过,除非此代码中缺少其他内容。
  • 为什么“try”和“except”中的代码一样???如果代码在“尝试”时失败,它将再次落在 except... 也许它在迭代 98 时失败。
  • 虽然,如果它第二次失败,那应该会导致未捕获的异常;除非此代码实际上包含在 try 中,否则会吞下错误。
  • 所以代码 [97] 的值是 2262011。我尝试使用相同的代码,除了因为有时 selenium 由于“陈旧元素异常”而失败并且无法按下搜索按钮,所以如果它失败了,然后从技术上讲,如果出现故障并且 selenium 找不到应该引发错误并停止循环的按钮,它会再次尝试。

标签: python selenium for-loop bots skip


【解决方案1】:

这里有几个问题:

  1. 你的定位器很糟糕。
  2. 我发现您的结果不正确。例如,对于“2262011”输入,输出是“Gdynia (2262011)”,而您正在为输入“2205084”呈现此输出
  3. 您的 except 代码与 try 代码类似。这没有意义。如果这在 try 块中不起作用,为什么您认为这将在第二次尝试时起作用而没有任何改变?
  4. 最好等待元素可见而不是出现,因为在元素刚刚呈现的那一刻,它还没有完全准备好被点击等等。
  5. 最好将元素定位器至少保留在类的顶部,而不是在代码中硬编码。

我试图让你的代码更好一点。
请尝试一下。

import time
import pandas
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

chrome_driver_path = "D:\Development\chromedriver.exe"
driver = webdriver.Chrome(chrome_driver_path)
driver.get("https://eteryt.stat.gov.pl/eTeryt/rejestr_teryt/udostepnianie_danych/baza_teryt/uzytkownicy_indywidualni/wyszukiwanie/wyszukiwanie.aspx?contrast=default")

# Get the column with the codes from excel sheet and redo it into the list.
data = pandas.read_excel(r"D:\NFZ\FINAL Baza2WUJEK(poprawione1)-plusostatniepoprawki.xlsx")
codes = data["Kody terytorialne"].tolist()

code_input_xpath = 'body_TabContainer1_TabPanel1_TBJPTIdentyfikator'
search_button_xpath = '//input[@id="body_TabContainer1_TabPanel1_BJPTWyszukaj"]'
city_xpath = '//table[@id="body_TabContainer1_TabPanel1_GVTERC"]//td/strong'



cities = []


iteration = 0

for code in codes:
    time.sleep(0.1)
    iteration += 1
    print(iteration)
    if code == "Absence":
        cities.append("Absence")
    elif code == "Error":
        cities.append("Error")
    elif code == 2211041 or code == 2211021:
        cities.append("Manual")
    else:
        # Send territorial code
        driver.find_element_by_xpath(code_input_xpath).clear()
        driver.find_element_by_xpath(code_input_xpath).send_keys(code)
        # Search
        button = WebDriverWait(driver, 20).until(
                EC.visibility_of_element_located((By.XPATH,search_button_xpath)))
            button.click()        
        # Scrape city name
        time.sleep(2)
        city = WebDriverWait(driver, 20).until(
            EC.visibility_of_element_located((By.XPATH, city_xpath))).text.split()
        print(code)
        print(city)
        cities.append(city)


table = {
    "Cities": cities
}

df = pandas.DataFrame.from_dict(table)
df.to_excel("cities-FINAL.xlsx")
driver.close()

【讨论】:

  • 您好,谢谢您的回答。我知道有些结果是不正确的,我不得不将睡眠时间从 4 秒降低到 0.05 秒,因此它创建了整个“与城市不正确相关的代码”混乱,因为我想更快地测试代码,因为它即使睡眠时间增加,也会以同样的方式失败。我以这种奇怪的方式实现了 try, except 方法,因为 selenium 有时会引发“无过时元素异常”,并且我读过使用这种符号运行问题引发代码两次可能会解决问题。
  • 非常感谢您的建议。您必须原谅我的代码混乱,我仍然是新手,但这肯定会帮助我提高。
  • 当然,好的,但是您是否尝试使用此代码?
  • 好的,我明白了。当代码发现其中一个异常时,它只是附加并仅打印迭代数,这就是为什么会有这种跳过的错觉。但这仍然不能解释为什么我第一手得到了不完整的清单。我会测试你的代码,如果它有帮助,我会告诉你。
  • 不,不。你误会我了。迭代号总是被打印出来,因为它是循环中的第一行代码,然后我们引发异常,如果代码捕获其中一个,它只会将异常名称附加到城市列表中,但在我们可以的 else 语句中解释为“没有错”语句不仅将城市名称附加到列表中,还打印城市名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多