Вопрос по python, beautifulsoup, memory – Высокое использование памяти Python с BeautifulSoup

9

Я пытался обработать несколько веб-страниц с BeautifulSoup4 в Python 2.7.3, но после каждого анализа использование памяти увеличивается и увеличивается.

Этот упрощенный код производит то же самое поведение:

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 МБ памяти (размер используемого HTML-файла был около 100 КБ), и он увеличивается на 4 МБ за каждый вызов. Есть ли способ освободить эту память или какой-то обходной путь?

Update: Такое поведение вызывает у меня головную боль. Этот код легко использует много памяти, хотя переменная 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()

Может быть, это какая-то ошибка?

30 МБ это не много, сборка мусора, возможно, еще не была запущена, я думаю .. есть проблема с памятью или что-то? Aprillion

Ваш Ответ

4   ответа
8

Попробуйте красивый супразлагаться функциональность, которая уничтожает дерево, когда вы закончите работать с каждым файлом.

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()
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, но как только вы введете непустую строку, он остановится для вас.

Спасибо за подсказку raw_input. К сожалению, использование диспетчера контекста не меняет поведение для меня Sesshu
2

Я знаю, что это старая ветка, но есть еще одна вещь, которую следует иметь в виду при разборе страниц с BeautifulSoup. Когда вы перемещаетесь по дереву и сохраняете определенное значение, обязательно получите строку, а не объект bs4. Например, это вызвало утечку памяти при использовании в цикле:

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

Что можно исправить, перейдя в:

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

В первом примере тип имени категории - bs4.element.NavigableString.

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

Даже при вызове gc.collect () между parse () и raw_input () эти 5 МБ не освобождаются. Sesshu
Это заставляет его перестать работать после одного вызова, но по какой-то причине первый вызов все еще использовал 5 МБ, которые не были освобождены. Sesshu
Я прошу прощения. Сбор произошел, когда предыдущий результат разбора был все еще ограниченpage, Сначала я должен был отключиться. Я обновил свой ответ.
@Sesshu: разве это не потому, что для первого вызова требуется 5 МБ, то это мусор, и сразу же после этого для следующего вызова требуется 5 МБ? Эти 5 МБ необходимы, чтобы сделать структуру index.html легко доступной.

Похожие вопросы