Python字符串非精确匹配场景下替代switch语句的方案探讨
我之前处理网页爬取的时候也遇到过一模一样的问题——那些网页标题要么有变体(比如Fees & Funding和Fees),要么偶尔有拼写错误,精确匹配的字典方案根本顶不住,链式if-elif-else写多了又像面条代码,维护起来头疼。这里有几个更灵活的替代方案,完美适配你的子串匹配需求:
解决方案:用关键词映射逻辑替代链式if-elif-else
方案1:关键词-函数映射列表(最直接好维护)
这个思路是把「关键词」和「对应的处理函数」做成一个有序列表,遍历每个标题时,检查列表里的关键词是否是标题的子串,找到第一个匹配的就执行对应函数。优点是逻辑清晰,调整匹配优先级、新增关键词都非常方便。
# 先定义各个板块的处理函数 def handle_overview(content): # 这里写处理overview板块的逻辑 print(f"Processing overview: {content.text[:50]}...") def handle_fees(content): # 处理fees/funding相关的逻辑 print(f"Processing fees/funding: {content.text[:50]}...") def handle_takeaways(content): # 处理takeaways板块的逻辑 print(f"Processing takeaways: {content.text[:50]}...") def handle_default(content): # 没有匹配到关键词时的默认处理 print(f"Processing unknown section: {content.text[:50]}...") # 定义关键词-函数映射列表,按匹配优先级排序(靠前的关键词先匹配) section_handlers = [ ("overview", handle_overview), ("fees", handle_fees), ("funding", handle_fees), # 把funding也映射到fees的处理函数 ("takeaways", handle_takeaways), # 可以随时添加新的关键词-函数对 ] # 遍历页面中的标题和内容 tags = browser.find_elements_by_xpath("//div[@class='main-content-entry']/h2") for tag in tags: heading = tag.get_attribute("textContent").lower().strip() content = tag.parent matched = False # 遍历映射列表,找第一个匹配的关键词 for keyword, handler in section_handlers: if keyword in heading: handler(content) matched = True break if not matched: handle_default(content)
为什么这个方案更好?
- 维护成本低:新增/修改关键词或者处理逻辑,只要调整
section_handlers列表或者对应的函数就行,不用动核心遍历代码。 - 支持多关键词对应同一函数:比如把
funding和fees都指向handle_fees,完美处理标题变体。 - 匹配优先级可控:把更常见、更精确的关键词放在列表前面,避免被宽泛的关键词提前匹配。
方案2:装饰器注册处理函数(更模块化)
如果你的处理函数比较多,想让每个函数和它负责的关键词绑定在一起,可以用装饰器来注册,代码结构会更清晰:
# 初始化一个处理函数注册表 section_handlers = [] def register_handler(*keywords): """装饰器:给处理函数注册要匹配的关键词""" def decorator(func): for keyword in keywords: section_handlers.append((keyword.lower(), func)) return func return decorator # 用装饰器注册处理函数,每个函数可以绑定多个关键词 @register_handler("overview") def handle_overview(content): print(f"Processing overview: {content.text[:50]}...") @register_handler("fees", "funding", "fees & funding") def handle_fees(content): print(f"Processing fees/funding: {content.text[:50]}...") @register_handler("takeaways", "key takeaways") def handle_takeaways(content): print(f"Processing takeaways: {content.text[:50]}...") def handle_default(content): print(f"Processing unknown section: {content.text[:50]}...") # 核心遍历逻辑和方案1完全一致 tags = browser.find_elements_by_xpath("//div[@class='main-content-entry']/h2") for tag in tags: heading = tag.get_attribute("textContent").lower().strip() content = tag.parent matched = False for keyword, handler in section_handlers: if keyword in heading: handler(content) matched = True break if not matched: handle_default(content)
这个方案的优势:
- 模块化更强:每个处理函数的职责和匹配关键词一目了然,不用在单独的列表里找对应关系。
- 扩展性好:新增处理板块时,直接写函数加装饰器就行,不用修改其他代码。
方案3:模糊匹配(应对拼写错误)
如果网页标题经常有拼写错误(比如把fees写成fes),可以用模糊字符串匹配来提高容错率。这里可以用fuzzywuzzy库(需要先安装:pip install fuzzywuzzy python-Levenshtein):
from fuzzywuzzy import fuzz # 定义关键词-函数映射 section_handlers = { "overview": handle_overview, "fees": handle_fees, "takeaways": handle_takeaways } # 遍历处理 tags = browser.find_elements_by_xpath("//div[@class='main-content-entry']/h2") for tag in tags: heading = tag.get_attribute("textContent").lower().strip() content = tag.parent # 计算标题和每个关键词的相似度,找最匹配的那个 max_similarity = 0 best_match_keyword = None for keyword in section_handlers: # partial_ratio用于子串模糊匹配,适合标题包含关键词的情况 similarity = fuzz.partial_ratio(keyword, heading) if similarity > max_similarity: max_similarity = similarity best_match_keyword = keyword # 设置相似度阈值(比如80分以上才认为匹配) if max_similarity >= 80: section_handlers[best_match_keyword](content) else: handle_default(content)
注意事项:
- 要调整合适的阈值:阈值太高会漏匹配,太低会误匹配,建议根据实际网页标题的错误情况调整。
- 性能:如果页面标题很多,模糊匹配会比精确子串匹配慢一点,不过一般爬取场景下影响不大。
总结
- 如果只是应对标题变体,方案1足够好用,简单直接易维护。
- 如果处理函数多、想更模块化,选方案2。
- 如果有大量拼写错误,再考虑方案3的模糊匹配。
内容的提问来源于stack exchange,提问作者thegreatjedi
相关产品推荐
相关产品推荐

