如何让bs4与requests编写的Python爬虫在持续运行时自动更新爬取数据
持续运行时数据不更新的核心原因
- 代码结构缺陷:现有爬虫逻辑如果写在全局作用域,Python只会在程序启动时执行一次请求、解析流程,哪怕程序一直在后台运行,也不会主动重复拉取数据
- 缓存机制干扰:
requests默认的长连接复用规则、雅虎财经边缘节点的缓存策略,会让持续运行的脚本通过旧连接直接返回历史缓存页面,不会加载实时更新的行情数据 - 反爬识别影响:固定的请求头、固定的请求间隔会被雅虎判定为无交互的爬虫流量,直接返回固定的静态缓存块,不会推送动态变动的价格内容
可落地的修复方案
- 将请求、解析逻辑封装为独立可调用的函数,放入循环结构中重复执行,从代码结构上保证每个定时节点都会触发新的爬取动作
- 每次请求手动携带禁止缓存的请求头,强制服务端不返回缓存内容;搭配随机User-Agent池、URL附带实时时间戳的方式,绕开边缘节点的URL层面缓存规则
- 不要长期复用同一个全局请求会话,每次爬取动作完成后主动关闭连接,避免长连接被标记为爬虫流量后持续返回固定内容
- 增加基础容错判断:如果两次爬取拿到的价格完全一致,可适当缩短间隔重试一次,排除临时缓存命中的问题
修正后的核心参考代码
import requests from bs4 import BeautifulSoup import time import random # 常用浏览器User-Agent池 USER_AGENTS = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0" ] def get_doge_price(): # 每次请求新建独立会话,不复用旧长连接 session = requests.Session() headers = { "User-Agent": random.choice(USER_AGENTS), "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache" } # 附加时间戳参数绕开URL层面缓存 target_url = f"https://finance.yahoo.com/quote/DOGE-USD/?t={int(time.time())}" # 设置10秒超时,避免连接卡死 r = session.get(target_url, headers=headers, timeout=10) session.close() soup = BeautifulSoup(r.content, features="html.parser") price_elem = soup.find("span", attrs={"class": "Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(ib)"}) return price_elem.text.strip() if price_elem else None if __name__ == "__main__": last_price = None while True: try: current_price = get_doge_price() # 价格变动且和上次记录不同的时候触发发推逻辑 if current_price and current_price != last_price: # 在此处接入Twitter发推功能 print(f"获取到最新狗狗币价格:{current_price}") last_price = current_price except Exception as e: print(f"本次请求异常:{str(e)}") # 每小时执行一次,加最多5分钟的随机偏移避免固定节奏被拦截 time.sleep(3600 + random.randint(0, 300))
长期运行注意事项
- 若出现解析不到元素的情况,先打印请求返回的内容长度,确认是否被反爬拦截返回了固定提示页
- 单次请求失败不要直接让程序退出,可设置2-3次自动重试逻辑,提升脚本稳定性
- 不要把和价格无关的全局变量、全局请求逻辑放在循环外执行,避免重复触发不必要的网络请求
内容的提问来源于stack exchange,提问作者jasonkunda00
相关产品推荐
相关产品推荐

