Python Gmarket爬虫schedule调度及数据、连接异常问题排查
问题排查与解决方案
1. 15分钟间隔调度任务URL连接失败,小时级定点任务正常
原理分析
- 核心原因是任务叠加引发的资源冲突或反爬触发:
schedule.every(15).minutes按固定间隔触发任务,若前一次check_start未完全执行(如网络超时、资源未释放),新任务会重复启动,导致g_market实例的连接状态紊乱;同时短时间高频请求容易触发目标网站的反爬策略,被拦截后出现连接失败。 - 小时级定点任务间隔足够长,前一次任务已彻底释放资源,且请求频率未达到反爬阈值,因此能正常连接。
解决步骤
- 强制任务串行执行:给
check_start加线程锁,确保同一时间仅一个任务实例运行:import threading task_lock = threading.Lock() def check_start(self): with task_lock: # 原有业务逻辑代码 - 彻底释放任务资源:每次
check_start执行完毕后,确保网络连接、浏览器驱动等资源被完全关闭,避免残留状态干扰下一次任务。 - 适配反爬策略:给请求添加1-3秒的随机延迟,轮换
User-Agent等请求头,降低短时间重复请求的风险。 - 优化调度逻辑:若使用
schedule.run_pending()循环,确保循环无阻塞;若用schedule.run_continuously(),设置合理的interval参数,防止任务堆积。
2. JSON导出仅记录首次爬取时间
原理分析
问题出在时间变量的初始化时机错误:你可能将datetime.datetime.now().strftime(...)的结果提前赋值给了全局变量或类初始化属性,后续导出JSON时一直复用这个初始值,而非每次爬取时实时获取当前时间。
解决步骤
- 移除提前赋值的时间变量,在生成JSON数据的实时环节调用时间函数:
# 错误写法(仅初始化一次) self.crawl_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S (%a)') # 正确写法(每次导出时实时获取) def export_to_json(self, crawl_data): export_data = { "data": crawl_data, "crawl_time": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S (%a)') } # 写入JSON文件的逻辑 - 若爬取与导出分离,需在爬取完成后立即记录当前时间,并将该时间与爬取数据绑定,避免复用全局时间值。
3. 间歇性出现MaxRetryError(与driver.quit()相关)
原理分析
driver.quit()未彻底释放端口:浏览器驱动(ChromeDriver/GeckoDriver)退出时可能存在进程残留,导致原端口被占用,下次启动驱动时无法绑定新连接。- 异常场景下未执行
quit():如果check_start执行中抛出异常,driver.quit()可能未被触发,驱动进程残留占用资源。 - 驱动退出后仍有代码调用:
quit()之后若还有逻辑访问driver的属性或方法,会触发对已关闭端口的重试请求,引发该错误。
解决步骤
- 用
try-finally确保驱动必退出:无论任务成功或失败,强制关闭驱动:def check_start(self): self.driver = None try: self.driver = webdriver.Chrome() # 或其他驱动初始化 # 爬取业务逻辑 finally: if self.driver: self.driver.close() # 先关闭当前窗口 self.driver.quit() # 再退出驱动进程 - 清理残留驱动进程:在任务启动前,检查并杀掉系统中残留的驱动进程(如
chromedriver.exe/geckodriver),避免端口占用。 - 检查驱动调用逻辑:确保
driver.quit()之后,没有任何代码再访问self.driver的属性或方法,若有则调整执行顺序或移除相关代码。 - 启用端口随机化:给驱动添加随机端口参数(如ChromeDriver用
--remote-debugging-port=0),避免固定端口被残留进程占用。
内容的提问来源于stack exchange,提问作者hanbit
相关产品推荐
相关产品推荐

