requests_html报Cannot allocate memory内存分配错误解决方案
问题根因
内存泄漏出在底层浏览器资源没释放,和你Python层关不关普通变量没关系,核心是三个问题:
r.html.render()开了keep_page=True,这个参数会让底层Pyppeteer调起的Chromium浏览器保留渲染页面对象,不会自动销毁。你每次循环跑一次请求,就多一个占内存的僵尸页面留在Chromium进程里,攒一天直接把0.5G内存吃满。你写的r.close()只能关Python层的响应对象,碰不到这些被标记为keep的浏览器页面资源。- 全局只建了一个
HTMLSession无限循环复用,requests-html本身不会自动回收长期运行产生的浏览器内存碎片、残留进程,跑的时间越久内存占得越多。 - 用了裸
except吞所有异常,只要请求、渲染过程中抛错,代码直接return None,根本走不到r.close()的逻辑,异常场景下的资源直接漏了。
修复方案
- 删掉
keep_page=True,除非你真的需要跨请求复用同一个渲染页面,不然这个参数保持默认False就行,渲染完自动销毁对应的Chromium页面。 - 别死攥着一个全局Session不放,每跑固定次数(比如10次请求)就主动把旧Session关了建个新的,把残留的Chromium进程彻底杀掉,清掉内存碎片。
- 把资源释放的逻辑挪到
finally块里,不管请求成不成功、报不报错,都确保响应对象能被关掉,别漏了异常分支的资源。 - 给Chromium加低内存启动参数,适配你这台0.5G内存的小机器,压一压浏览器本身的内存开销。
修复后参考代码
import time from requests_html import HTMLSession from bs4 import BeautifulSoup as BS # Chromium低内存启动参数 browser_args = [ '--no-sandbox', '--disable-dev-shm-usage', '--disable-extensions', '--disable-gpu', '--disable-default-apps', '--no-zygote' ] headers = {'accept': '*/*', 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'} url = "my_url" def get_site(session, site, params): r = None try: r = session.get(site, headers=headers, verify=False) script = """ () =>{ $('.WEB_APPOINT_FORWARDBUTTON').click(); } """ # 移除keep_page=True,传入低内存参数 r.html.render(script=script, sleep=5, browser_args=browser_args) soup = BS(r.html.html, 'html.parser') info = soup.find("div", {"id": "location"}).find_all("td", {"class": "calendar"}) return info except Exception: return None finally: # 所有场景下都确保释放响应资源 if r: try: r.close() except: pass if __name__ == "__main__": request_count = 0 ses = HTMLSession(browser_args=browser_args) while True: params = "same info" rez = get_site(ses, url, params) request_count += 1 # 每10次请求重建一次Session,彻底清理Chromium残留进程 if request_count % 10 == 0: ses.close() ses = HTMLSession(browser_args=browser_args) time.sleep(30)
额外说明:0.5G内存的机器跑Chromium本身冗余空间很小,如果修复后还是有缓慢内存上涨的情况,可以把重建Session的频率调高,比如每3-5次请求就重建一次,也可以直接在系统层面加定时任务,每天低峰期自动重启一次脚本,彻底释放所有内存。
内容的提问来源于stack exchange,提问作者The person with the question
相关产品推荐
相关产品推荐

