You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenium爬取卫福署医院查询站遇NoSuchElementException问题求助

问题解决:Selenium爬取医院查询网站元素定位失败

以下是针对你遇到的NoSuchElementException错误的具体解决方案:

1. 排查验证码识别有效性

验证码识别错误会导致搜索后无结果页面,自然找不到目标元素。添加结果校验逻辑:

# 点击搜索后,先检查是否无结果
try:
    no_result = WebDriverWait(browser, 10).until(
        EC.presence_of_element_located((By.XPATH, '//*[contains(text(), "查無資料")]'))
    )
    print(f"第{i}条:{df['New_Name'][i]} 无匹配结果")
    code_list.append("无结果")
    name_list.append(df['New_Name'][i])
    address_list.append("无结果")
    browser.quit()
    continue
except:
    pass

2. 替换动态ID为稳定定位策略

目标元素的ID包含动态后缀ctl02,会随结果行数或页面渲染变化,改用基于表格结构的定位:

# 等待结果表格加载,定位第一行的详情链接
WebDriverWait(browser, 20).until(
    EC.presence_of_element_located((By.ID, 'ctl00_ContentPlaceHolder1_gviewMain'))
)
# 定位结果表格第二行(第一行是表头)的第一个链接
detail = WebDriverWait(browser, 20).until(
    EC.element_to_be_clickable((By.XPATH, '//table[@id="ctl00_ContentPlaceHolder1_gviewMain"]//tr[2]//a'))
)
detail.click()

如果需要匹配医院名称,也可以用文本包含定位:

detail = WebDriverWait(browser, 20).until(
    EC.element_to_be_clickable((By.XPATH, f'//a[contains(text(), "{df["New_Name"][i]}")]'))
)

3. 修复Headless模式渲染问题

Headless模式下页面渲染可能不全,添加窗口大小和反检测参数:

chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument('--no-sandbox')
# 添加窗口大小参数,确保页面完整渲染
chrome_options.add_argument("--window-size=1920,1080")
# 反自动化检测
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)

4. 优化验证码截图逻辑

避免因屏幕缩放导致的坐标偏移,直接截取验证码元素:

# 直接截取验证码元素,无需整个页面截图
element = browser.find_element(By.ID, 'ctl00_ContentPlaceHolder1_ImageCheck')
element.screenshot(f'C:/Users/jlee72/Desktop/Hos/selenium + captcha/{i}.jpg')

5. 优化等待逻辑,移除固定sleep

替换time.sleep(10)为显式等待,确保元素加载完成后再操作:

# 等待搜索按钮点击后结果表格出现
WebDriverWait(browser, 20).until(
    EC.presence_of_element_located((By.ID, 'ctl00_ContentPlaceHolder1_gviewMain'))
)
# 再等待详情链接可点击
detail = WebDriverWait(browser, 20).until(
    EC.element_to_be_clickable((By.XPATH, '//table[@id="ctl00_ContentPlaceHolder1_gviewMain"]//tr[2]//a'))
)
detail.click()

修改后的完整代码片段

from selenium import webdriver
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import ddddocr
from selenium.webdriver.chrome.options import Options
import pandas as pd

df = pd.read_csv('hos.csv')

code_list = []
name_list = []
address_list = []

for i in range(len(df)):
    chrome_options = Options()
    chrome_options.add_argument("--headless")
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument("--window-size=1920,1080")
    chrome_options.add_argument("--disable-blink-features=AutomationControlled")
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    
    browser = webdriver.Chrome(options=chrome_options)
    browser.get('https://ma.mohw.gov.tw/masearch/')

    # 截取验证码元素
    element = browser.find_element(By.ID, 'ctl00_ContentPlaceHolder1_ImageCheck')
    element.screenshot(f'C:/Users/jlee72/Desktop/Hos/selenium + captcha/{i}.jpg')               
    print(f'已保存验证码截图:{i}.jpg')

    # 识别验证码
    ocr = ddddocr.DdddOcr()
    with open(f'C:/Users/jlee72/Desktop/Hos/selenium + captcha/{i}.jpg', 'rb') as f:
        img_bytes = f.read()
    res = ocr.classification(img_bytes)
    print(f'验证码识别结果:{res}')

    try:
        # 输入医院名称
        Institution_name = browser.find_element(By.ID, 'ctl00_ContentPlaceHolder1_txtBAS_NAME')
        Institution_name.send_keys(df['New_Name'][i]) 

        # 输入验证码
        Institution_code = browser.find_element(By.ID, 'ctl00_ContentPlaceHolder1_TextBox1') 
        Institution_code.send_keys(res) 

        # 点击搜索
        login = browser.find_element(By.ID, 'ctl00_ContentPlaceHolder1_btnSearch')
        login.click()  

        # 检查是否无结果
        try:
            no_result = WebDriverWait(browser, 10).until(
                EC.presence_of_element_located((By.XPATH, '//*[contains(text(), "查無資料")]'))
            )
            print(f"第{i}条:{df['New_Name'][i]} 无匹配结果")
            code_list.append("无结果")
            name_list.append(df['New_Name'][i])
            address_list.append("无结果")
            browser.quit()
            continue
        except:
            pass

        # 等待结果表格加载,定位详情链接
        WebDriverWait(browser, 20).until(
            EC.presence_of_element_located((By.ID, 'ctl00_ContentPlaceHolder1_gviewMain'))
        )
        detail = WebDriverWait(browser, 20).until(
            EC.element_to_be_clickable((By.XPATH, '//table[@id="ctl00_ContentPlaceHolder1_gviewMain"]//tr[2]//a'))
        )
        detail.click()   

        # 后续获取编码和地址的逻辑
        hos_code = WebDriverWait(browser, 20).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="ctl00_ContentPlaceHolder1_lblBAS_ID"]'))
        ).text
        hos_address = WebDriverWait(browser, 20).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="ctl00_ContentPlaceHolder1_lblBAS_ADDR"]'))
        ).text

        code_list.append(hos_code)
        name_list.append(df['New_Name'][i])
        address_list.append(hos_address)
        
    except Exception as e:
        print(f"第{i}条处理失败:{str(e)}")
        code_list.append("处理失败")
        name_list.append(df['New_Name'][i])
        address_list.append("处理失败")
    finally:
        browser.quit()

# 保存结果
result_df = pd.DataFrame({
    '医院名称': name_list,
    '医院编码': code_list,
    '医院地址': address_list
})
result_df.to_csv('hos_result.csv', index=False, encoding='utf-8-sig')

内容的提问来源于stack exchange,提问作者Duh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 13:35:22