Python多线程运行4个无限循环房产监控函数仅首个线程执行问题
核心问题定位
- 代码执行顺序完全错位:主流程中编写的4个串行
while True无限循环直接阻塞了整个程序运行。Python 按从上到下的顺序执行代码时,进入第一个无限循环后就永远无法运行到后续的线程启动代码段。所谓“仅第一个线程能正常执行、其余线程无响应”,本质是程序根本没有走到多线程启动环节,所有逻辑都卡在第一个串行无限循环里。 - 爬取函数逻辑失效:每个爬取函数内部虽然编写了
while True无限循环,但请求成功拿到广告链接后直接执行return返回值,会直接跳出当前函数,循环无法持续执行,完全不符合“无限循环持续运行爬取逻辑”的设计要求。 - 核心业务逻辑缺失:没有实现“定时采集、对比链接变化识别新发广告”的逻辑,没有维护存储历史链接的状态变量,所有定时休眠、链接对比的代码都写在了永远无法执行到的串行循环块中,全局共用的
first_run变量也会导致多个区域的判断逻辑互相干扰。
修正方案
- 完全删除主流程中编写的4个串行无限循环块,所有定时爬取、链接对比的逻辑封装到每个线程对应的业务函数内部,通过公共状态字典存储各区域的历史链接,避免变量互相干扰。
- 调整函数内部执行流程:进入循环后先发起爬取请求,拿到首页第一条广告链接后,和对应区域的历史链接做对比,识别到链接变化时输出新广告提示,之后按设定的时间间隔休眠,再进入下一轮爬取。
- 启动线程时设置守护线程属性,避免主程序退出时线程残留无法回收,最后通过主线程的短间隔休眠阻塞主线程,避免主线程退出导致所有守护线程终止。
修正后的可运行代码
import time import threading import requests from bs4 import BeautifulSoup headers = {'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36'} # 分区域存储历史广告链接,用于变化对比 region_link_state = { "carrigaline": None, "crosshaven": None, "minane": None, "ballygarvan": None } def region_crawler(target_url, region_name, crawl_interval): while True: try: page = requests.get(target_url, headers=headers).text soup = BeautifulSoup(page, 'html.parser') ad_links = soup.findAll('a', attrs={'class': None}) current_link = '目标站点根域名' + ad_links[0].get('href') # 首次运行直接记录初始链接 if region_link_state[region_name] is None: region_link_state[region_name] = current_link # 对比链接变化识别新发广告 if current_link != region_link_state[region_name]: print(f"{region_name}区域检测到新发广告:{current_link}") region_link_state[region_name] = current_link except Exception as e: print(f"{region_name}区域爬取异常:{e}") # 按设定间隔休眠,控制请求频率 time.sleep(crawl_interval) if __name__ == "__main__": # 初始化4个独立线程,每个线程对应一个区域的爬取任务 thread_list = [ threading.Thread(target=region_crawler, args=('区域1爬取URL', 'carrigaline', 360), daemon=True), threading.Thread(target=region_crawler, args=('区域2爬取URL', 'minane', 300), daemon=True), threading.Thread(target=region_crawler, args=('区域3爬取URL', 'crosshaven', 420), daemon=True), threading.Thread(target=region_crawler, args=('区域4爬取URL', 'ballygarvan', 540), daemon=True) ] # 启动所有线程 for t in thread_list: t.start() # 阻塞主线程,避免主线程退出导致所有守护线程终止 while True: time.sleep(1)
内容的提问来源于stack exchange,提问作者Abhishek Rai
相关产品推荐
相关产品推荐

