2012-07-01 35 views
7

Tôi đã cố gắng xử lý một số trang web với BeautifulSoup4 trong python 2.7.3 nhưng sau mỗi lần phân tích mức sử dụng bộ nhớ tăng lên và tăng lên.Sử dụng bộ nhớ cao của Python với BeautifulSoup

đang đơn giản hóa này tạo ra những hành vi tương tự:

from bs4 import BeautifulSoup 

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

while True: 
    parse() 
    raw_input() 

Sau khi gọi parse() cho năm lần so với quá trình trăn đã sử dụng 30 MB bộ nhớ (sử dụng tập tin HTML là khoảng 100 kB) và nó đi lên bằng 4 MB mỗi cuộc gọi. Có cách nào để giải phóng bộ nhớ đó hoặc một số cách giải quyết khác không?

Cập nhật: Hành vi này khiến tôi đau đầu. Mã này dễ dàng sử dụng nhiều bộ nhớ mặc dù biến BeautifulSoup sẽ bị xóa vĩnh viễn:

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() 

Có thể là một loại lỗi nào đó?

+0

30 MB không nhiều, bộ sưu tập rác có thể chưa được kích hoạt nhưng tôi đoán .. có vấn đề gì với bộ nhớ hay gì đó không? – Aprillion

Trả lời

2

Cố gắng thu rác:

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() 

Xem thêm:

Python garbage collection

+0

Điều này làm cho nó ngừng đi lên sau một cuộc gọi nhưng vì lý do nào đó cuộc gọi đầu tiên vẫn được sử dụng 5 MB mà không được giải phóng. – Sesshu

+0

@Sesshu: không phải là vì cuộc gọi đầu tiên cần 5MB, sau đó nó là rác thu thập được và ngay lập tức sau đó cuộc gọi tiếp theo cần 5MB? 5MB đó là cần thiết để làm cho cấu trúc của index.html dễ truy cập được. –

+0

Ngay cả khi gọi gc.thu thập() giữa phân tích cú pháp() và raw_input() 5 MB đó không được giải phóng. – Sesshu

0

Thu gom rác có lẽ là khả thi, nhưng một người quản lý bối cảnh dường như xử lý nó khá tốt cho tôi mà không cần bất kỳ sử dụng bộ nhớ thêm :

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

Ngoài ra, tho ugh không hoàn toàn cần thiết, nếu bạn đang sử dụng raw_input để cho nó vòng lặp trong khi bạn kiểm tra tôi thực sự tìm thấy thành ngữ này khá hữu ích:

while not raw_input(): 
    parse() 

Nó sẽ tiếp tục vòng lặp mỗi lần bạn nhấn enter, nhưng ngay sau khi bạn nhập bất kỳ chuỗi không trống nào nó sẽ dừng cho bạn.

+0

Cảm ơn mẹo raw_input. Thật không may khi sử dụng trình quản lý ngữ cảnh không thay đổi hành vi đối với tôi – Sesshu

4

Hãy thử chức năng decompose của Beautiful Soup, phá hủy cây, khi bạn hoàn thành công việc với từng tệp.

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() 
2

Tôi biết đây là một chủ đề cũ, nhưng có một điều nữa cần lưu ý khi phân tích các trang bằng beautifulsoup. Khi điều hướng một cây, và bạn đang lưu trữ một giá trị cụ thể, hãy chắc chắn để có được chuỗi và không phải là một đối tượng bs4. Đối với trường hợp này gây ra rò rỉ bộ nhớ khi sử dụng trong một vòng lặp:

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

Mà có thể được cố định bằng cách thay đổi trong thành:

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

Trong ví dụ đầu tiên loại tên loại là bs4.element. NavigableString

Các vấn đề liên quan