Python爬虫占用内存不断增大,如何释放?
本帖最后由 lsr314 于 2021-12-3 11:38 编辑最近在写一个爬虫,从网站上下载上市公司年报和公告,并保存到本地,用到了requests.get()和urllib.request.Request()、urllib.request.urlopen()这几个函数。
程序可以正确执行,但是每下载一个文件,python.exe进程占用的内存就会增加,每次增加的大小大约就是1-2个下载的文件的大小。不久系统内存就满了。
通过debug,发现主要是在执行urllib.request.urlopen().read()的时候,内存会增加。
想问有什么办法可以在程序运行的过程中释放内存,或者让它自己停止,并且释放内存后重新启动,接着上次的进度继续运行下去?
下面是程序的核心部分,后面还有对公司代码的for循环,这里就不贴了:
def get_file(url, path):
try:
req = urllib.request.Request(url, headers=headers)
data = urllib.request.urlopen(req).read()# 这一步持续增加占用内存
with open(path, 'wb') as f:
f.write(data)
f.close()
except Exception as e:
print(e)
print('获取文件失败')
1) 既然是内存泄漏了. 那么urllib.request.urlopen(req) 之后 好像还应该close掉这个句柄.
2) with open 之后不需要再close.
3) 试试python3的requests. 替代urllib.
def get_file(url, path):
try:
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req, data=login_data.encode('utf-8')) as u:
data = u.read()
with open(path, 'wb') as f:
f.write(data)
except Exception as e:
print(e)
print('获取文件失败') wayne 发表于 2021-12-3 12:30
1) 既然是内存泄漏了. 那么urllib.request.urlopen(req) 之后 好像还应该close掉这个句柄.
2) with open...
按这个办法运行了一下,python.exe内存占用还是持续在增加。
headers里已经包括cookies信息了,所以在urllib.request.urlopen()没有加data=login_data.encode('utf-8')这个参数,应该不会是这个问题吧? wayne 发表于 2021-12-3 12:30
1) 既然是内存泄漏了. 那么urllib.request.urlopen(req) 之后 好像还应该close掉这个句柄.
2) with open...
我也不喜欢用urllib,不过用requests是怎么替代的?一般网页我会直接用requests.get(),但是这个好像不能下载文件 试了下 requests下载文件, 支持 进度条更新 和 断点续传.
参考文章, https://www.justdopython.com/2020/11/16/python-downloadFile/
import os,re
import requests
import tqdm
def download_file(url, file):
resp = requests.get(url+file, stream=True)
file_size = int(resp.headers['content-length'])
print('{0} ,filesize: = {1:.3f} MB'.format(file, file_size/1024./1024.))
with requests.get(url+file, stream=True) as r:
with open(file, 'wb') as fp:
for chunk in r.iter_content(chunk_size=1024):
if chunk:
fp.write(chunk)
def tqdm_download(url, file_name):
r = requests.get(url + file_name, stream=True)
# 获取文件大小
file_size = int(r.headers['content-length'])
# 如果文件存在获取文件大小,否在从 0 开始下载,
first_byte = 0
if os.path.exists(file_name):
first_byte = os.path.getsize(file_name)
# 判断是否已经下载完成
if first_byte >= file_size:
return
# Range 加入请求头
header = {"Range": f"bytes={first_byte}-{file_size}",
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.3538.77 Safari/537.36'}
# 加了一个 initial 参数
with tqdm.tqdm(total=file_size, unit='B', initial=first_byte, unit_scale=True, unit_divisor=1024, ascii=True, desc=file_name) as bar:
# 加 headers 参数
with requests.get(url + file_name, headers=header, stream=True) as r:
with open(file_name, 'ab') as fp:
for chunk in r.iter_content(chunk_size=512):
if chunk:
fp.write(chunk)
bar.update(len(chunk))
u='https://mirrors.cloud.tencent.com/qt/official_releases/qt/6.2/6.2.2/submodules/'
r = requests.get(u)
res = re.findall(r'([\w+\-\.]+xz)</a>', r.text)
for file in res:
# download_file(u, file)
tqdm_download(u, file)
lsr314 发表于 2021-12-3 18:18
按这个办法运行了一下,python.exe内存占用还是持续在增加。
headers里已经包括cookies信息了,所以在ur ...
你是怎么确定内存一直在增加.我用上面的代码测试 下载了10分钟左右, pycharm内存占用很稳定. 有时增加有时候减少.
页:
[1]