9

我试图在 python 2.7.3 中使用 BeautifulSoup4 处理几个网页,但每次解析后内存使用量都会上升。

此简化代码产生相同的行为:

from bs4 import BeautifulSoup

def parse():
    f = open("index.html", "r")
    page = BeautifulSoup(f.read(), "lxml")
    f.close()

while True:
    parse()
    raw_input()

在调用 parse() 五次后,python 进程已经使用了 30 MB 的内存(使用的 HTML 文件大约 100 kB)并且每次调用都会增加 4 MB。有没有办法释放该内存或某种解决方法?

更新: 这种行为让我头疼。即使 BeautifulSoup 变量应该被长期删除,这段代码也很容易占用大量内存:

from bs4 import BeautifulSoup
import threading, httplib, gc

class pageThread(threading.Thread):
    def run(self):
        con = httplib.HTTPConnection("stackoverflow.com")
        con.request("GET", "/")
        res = con.getresponse()
        if res.status == 200:
            page = BeautifulSoup(res.read(), "lxml")
        con.close()

def load():
    t = list()
    for i in range(5):
        t.append(pageThread())
        t[i].start()
    for thread in t:
        thread.join()

while not raw_input("load? "):
    gc.collect()
    load()

这可能是某种错误吗?

4

4 回答 4

10

尝试使用 Beautiful Soup 的分解功能,它会在您处理完每个文件后破坏树。

from bs4 import BeautifulSoup

def parse():
    f = open("index.html", "r")
    page = BeautifulSoup(f.read(), "lxml")
    # page extraction goes here
    page.decompose()
    f.close()

while True:
    parse()
    raw_input()
于 2013-01-16T02:34:47.683 回答
4

我知道这是一个旧线程,但是在使用 beautifulsoup 解析页面时还有一件事要记住。导航树时,如果要存储特定值,请确保获取字符串而不是 bs4 对象。例如,这在循环中使用时会导致内存泄漏:

category_name = table_data.find('a').contents[0]

可以通过更改为:

category_name = str(table_data.find('a').contents[0])

在第一个示例中,类别名称的类型是 bs4.element.NavigableString

于 2017-03-01T15:32:00.333 回答
2

尝试垃圾收集:

from bs4 import BeautifulSoup
import gc

def parse():
    f = open("index.html", "r")
    page = BeautifulSoup(f.read(), "lxml")
    page = None
    gc.collect()
    f.close()

while True:
    parse()
    raw_input()

也可以看看:

Python 垃圾回收

于 2012-07-01T20:05:27.533 回答
0

垃圾收集可能是可行的,但上下文管理器似乎对我来说处理得很好,没有任何额外的内存使用:

from bs4 import BeautifulSoup as soup
def parse():
  with open('testque.xml') as fh:
    page = soup(fh.read())

此外,虽然不是完全必要的,但如果您在raw_input测试时使用让它循环,我实际上发现这个成语非常有用:

while not raw_input():
  parse()

每次您按 Enter 时它都会继续循环,但是一旦您输入任何非空字符串,它就会为您停止。

于 2012-07-01T20:18:00.210 回答