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

Flask输入字段特定错误处理:限制字段合法值问题

问题

我正在开发一个爬虫网站,包含三个输入字段(第二个为可选字段)。目前当用户未填写第一个或第三个字段时,系统会显示对应的空字段错误提示;但我需要限制第三个字段仅能输入wohnung或haus,现有代码无法实现该验证——用户输入其他值时,系统仍会提示“Scraping started!”,而非像空字段那样显示错误。

现有代码

run_scraper函数

def run_scraper(city, subregion, apart_or_house):
    # Ask the user for input
    base_url = ""
    while True:
        if city != "":
            break
        else:
            flash("City name cannot be empty. Please enter a valid city name.", "error")
            return

    while True:
        if apart_or_house == "wohnung" or apart_or_house == 'haus':
            break
        elif apart_or_house == "":
            flash("This field cannot be empty. Please enter what are you buying.", "error")
        else:
            flash("Please enter either 'wohnung' or 'haus'.", "error")
            return

    if subregion:
        base_url = f"https://www.immobilienscout24.de/Suche/de/{city}/{city}/{subregion}/{apart_or_house}-kaufen"
    else:
        base_url = f"https://www.immobilienscout24.de/Suche/de/{city}/{city}/{apart_or_house}-kaufen"

    #Run the scraper script with the provided inputs and base_url
    subprocess.run(['python', 'scraper.py', city, subregion, apart_or_house, base_url])
    session['scraping_finished'] = True
    flash('Scraper has finished!', 'info')
    g.scraping_finished = True

路由代码

@app.route('/scrape', methods=['GET', 'POST'])
def scrape():
    form = ScrapingForm()
    if form.validate_on_submit():
        city = request.form.get('city')
        subregion = request.form.get('subregion')
        apart_or_house = request.form.get('apart_or_house')

        if city and apart_or_house:
            g.scraping_finished = False
            threading.Thread(target=run_scraper, args=(city, subregion, apart_or_house)).start()
            flash('Scraping started!', 'success')
        else:
            flash('Please fill all required fields.', 'error')

    if g.get('scraping_finished', False):
        flash('Scraper has finished!', 'info')

    return render_template('scrape.html', form=form)

问题原因

原代码的核心问题是校验逻辑与业务逻辑分离错误:

  1. 路由仅检查city和apart_or_house非空,就直接启动爬虫线程并弹出“Scraping started!”,完全跳过了第三个字段的有效值校验。
  2. run_scraper里的校验逻辑在线程中执行,而Flask的flash、session、g都依赖请求上下文,线程中没有这个上下文,导致校验错误无法正常显示给用户。

解决方案

把所有输入校验移到路由的请求主线程中完成,确认输入合法后再启动爬虫线程;同时简化run_scraper,只负责执行爬虫逻辑。

修改后的路由代码

@app.route('/scrape', methods=['GET', 'POST'])
def scrape():
    form = ScrapingForm()
    if form.validate_on_submit():
        city = request.form.get('city').strip()
        subregion = request.form.get('subregion', '').strip()
        apart_or_house = request.form.get('apart_or_house').strip()

        # 统一在主线程完成所有输入校验
        error_msg = None
        if not city:
            error_msg = "City name cannot be empty. Please enter a valid city name."
        elif not apart_or_house:
            error_msg = "This field cannot be empty. Please enter what are you buying."
        elif apart_or_house not in ('wohnung', 'haus'):
            error_msg = "Please enter either 'wohnung' or 'haus'."
        
        if error_msg:
            flash(error_msg, 'error')
        else:
            g.scraping_finished = False
            threading.Thread(target=run_scraper, args=(city, subregion, apart_or_house)).start()
            flash('Scraping started!', 'success')

    if g.get('scraping_finished', False):
        flash('Scraper has finished!', 'info')

    return render_template('scrape.html', form=form)

修改后的run_scraper函数

def run_scraper(city, subregion, apart_or_house):
    # 直接生成URL,输入已在路由校验过
    base_url = (f"https://www.immobilienscout24.de/Suche/de/{city}/{city}/{subregion}/{apart_or_house}-kaufen"
                if subregion 
                else f"https://www.immobilienscout24.de/Suche/de/{city}/{city}/{apart_or_house}-kaufen")

    # 执行爬虫脚本
    subprocess.run(['python', 'scraper.py', city, subregion, apart_or_house, base_url])
    
    # 线程中操作Flask上下文需要手动激活
    with app.app_context():
        session['scraping_finished'] = True
        g.scraping_finished = True
        flash('Scraper has finished!', 'info')

补充说明

  • 线程中操作session和g时,必须手动激活应用上下文(with app.app_context()),否则会抛出上下文不存在的错误。
  • 如果异步任务更复杂,推荐使用Flask-Executor或Celery这类专门的异步任务工具,比原生线程更稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:17:06