ESP32 MicroPython HTTP请求优化:解决网页读取内存不足问题
解决ESP32 MicroPython抓取大网页的内存分配问题
1. 流式读取响应,避免加载整个网页
urequests的响应对象支持流式读取,无需一次性调用response.text(该操作会把整个网页加载到内存)。直接读取响应的原始字节流,每次读一小段,找到目标内容后立即终止请求并释放连接:
import urequests import gc gc.collect() url = "https://www.heizpellets24.de" resp = urequests.get(url, stream=True) target_found = False buffer = bytearray() # 每次读取512字节的小块数据 for chunk in resp.iter_content(chunk_size=512): buffer.extend(chunk) # 替换为实际的目标HTML标签,比如价格对应的标记 if b'<div class="product-price">' in buffer: # 从缓冲区中提取目标数值 start_idx = buffer.find(b'<div class="product-price">') + len(b'<div class="product-price">') end_idx = buffer.find(b'</div>', start_idx) price = buffer[start_idx:end_idx].strip().decode('utf-8') target_found = True break # 防止缓冲区过大,定期保留最后1024字节(避免遗漏标签) if len(buffer) > 2048: buffer = buffer[-1024:] resp.close() # 必须关闭连接释放资源 if target_found: print(f"提取到价格: {price}")
这种方式仅在内存中保留一小段响应内容,不会触发大内存分配请求。
2. 用结构化标签匹配替代偏移量
放弃固定偏移量提取,改为基于HTML的标签特征(如class、id属性)匹配,既避免网页微小改动导致失效,也能更精准定位目标。比如目标价格在<span id="current-price">标签内,就直接匹配该id的标签,而非依赖字符位置。
如果不想引入第三方库,可自行编写简单的状态机流式处理字节流中的标签;也可以使用MicroPython生态的轻量HTML解析库(如适配MicroPython的tinyhtmlparser),避免占用过多内存。
3. 优化内存碎片与分配
虽然显示有89952字节空闲,但内存碎片可能导致无法分配连续的20000字节块,可尝试:
- 在发起请求前多次调用
gc.collect(),且尽量在项目其他大内存模块未运行时执行抓取操作 - 避免在循环中频繁创建大字符串或字节对象,尽量复用现有缓冲区(如上述代码中的
bytearray) - 临时关闭非必要的功能模块(如闲置传感器、无关连接),抓取完成后再恢复,释放额外内存
4. 减少HTTP请求的数据量
通过HTTP请求头的Accept-Encoding字段,请求服务器返回压缩后的内容(如gzip),大幅减少传输的数据量:
headers = {'Accept-Encoding': 'gzip'} resp = urequests.get(url, headers=headers, stream=True)
部分版本的urequests支持自动解压,也可使用uzlib模块手动解压chunk,虽增加少量CPU开销,但能显著降低内存占用。
内容的提问来源于stack exchange,提问作者Fab_ME
相关产品推荐
相关产品推荐

