2013-03-19 34 views
17

Có cách nào để xác định chiều rộng thụt lề tùy chỉnh cho chức năng .prettify() không? Từ những gì tôi có thể lấy từ nguồn của nó -Chiều rộng thụt lề tùy chỉnh cho BeautifulSoup .prettify()

def prettify(self, encoding=None, formatter="minimal"): 
    if encoding is None: 
     return self.decode(True, formatter=formatter) 
    else: 
     return self.encode(encoding, True, formatter=formatter) 

Không có cách nào để chỉ định chiều rộng thụt lề. Tôi nghĩ rằng đó là vì dòng này trong decode_contents() chức năng -

s.append(" " * (indent_level - 1)) 

nào có chiều dài cố định trong tổng số 1 không gian! (TẠI SAO !!) Tôi đã thử chỉ định indent_level=4, điều đó chỉ dẫn đến kết quả này -

<section> 
    <article> 
     <h1> 
     </h1> 
     <p> 
     </p> 
    </article> 
    </section> 

Trông chỉ đơn giản là ngu ngốc. : |

Bây giờ, tôi có thể hack điều này đi, nhưng tôi chỉ muốn chắc chắn nếu có bất cứ điều gì tôi đang thiếu. Bởi vì đây nên là một tính năng cơ bản. : -/

Nếu bạn có một số cách tốt hơn để tạo mã HTML, hãy cho tôi biết.

+0

Trong câu trả lời cho câu hỏi phụ của bạn ("TẠI SAO!"): HTML và XML có xu hướng rất, lồng nhau rất sâu, và tôi đoán những kẻ xấu như cửa sổ 80 cột. Nhưng bạn có thể muốn đăng lên danh sách/nhóm gửi thư và/hoặc gửi một lỗi yêu cầu tính năng này (và vì bản vá khá đơn giản — và ramabodhi đã viết khá nhiều cho bạn - bạn nên đưa nó vào email/lỗi của mình bài báo cáo). – abarnert

+0

Có vẻ như ai đó đã gửi một bản vá tương tự với 3,2 đến danh sách gửi thư cách đây vài năm. Xem [tại đây] (https://groups.google.com/forum/?fromgroups=#!topic/beautifulsoup/B4qryJpJqpY). – abarnert

+0

"Thụt lề 1-không gian trông chỉ đơn giản là ngu ngốc.: |" - Cảm ơn bạn. Đây là chính xác những gì tôi đã suy nghĩ khi tôi đang tìm kiếm vấn đề này. – Brandin

Trả lời

11

Tôi thực sự xử lý điều này bản thân mình, theo cách hackiest nhất có thể: bằng cách xử lý hậu quả kết quả.

r = re.compile(r'^(\s*)', re.MULTILINE) 
def prettify_2space(s, encoding=None, formatter="minimal"): 
    return r.sub(r'\1\1', s.prettify(encoding, formatter)) 

Thực ra, tôi monkeypatched prettify_2space ở vị trí của prettify trong lớp. Đó không phải là điều cần thiết để các giải pháp, nhưng chúng ta hãy làm điều đó dù sao, và làm cho sự thụt lề rộng một tham số thay vì hardcoding nó để 2:

orig_prettify = bs4.BeautifulSoup.prettify 
r = re.compile(r'^(\s*)', re.MULTILINE) 
def prettify(self, encoding=None, formatter="minimal", indent_width=4): 
    return r.sub(r'\1' * indent_width, orig_prettify(self, encoding, formatter)) 
bs4.BeautifulSoup.prettify = prettify 

Vì vậy:

x = '''<section><article><h1></h1><p></p></article></section>''' 
soup = bs4.BeautifulSoup(x) 
print(soup.prettify(indent_width=3)) 

... cung cấp cho:

<html> 
    <body> 
     <section> 
     <article> 
      <h1> 
      </h1> 
      <p> 
      </p> 
     </article> 
     </section> 
    </body> 
</html> 

Rõ ràng nếu bạn muốn vá Tag.prettify cũng như BeautifulSoup.prettify, bạn phải làm điều tương tự ở đó. (Bạn có thể muốn tạo một trình bao bọc chung chung mà bạn có thể áp dụng cho cả hai, thay vì lặp lại chính mình.) Và nếu có bất kỳ phương thức khác prettify, cùng một thỏa thuận.

4

Theo như tôi có thể biết, tính năng này không được tích hợp, vì có một số giải pháp ngoài đó cho vấn đề này. .

Giả sử bạn đang sử dụng BeautifulSoup 4, đây là những giải pháp tôi đến với

hardcode nó trong Điều này đòi hỏi thay đổi tối thiểu, điều này là tốt nếu bạn không cần phải thụt lề phải khác nhau trong những hoàn cảnh khác nhau:

myTab = 4 # add this 
if pretty_print: 
    # space = (' ' * (indent_level - 1)) 
    space = (' ' * (indent_level - myTab)) 
    #indent_contents = indent_level + 1 
    indent_contents = indent_level + myTab 

Một vấn đề khác với giải pháp trước đó là nội dung văn bản sẽ không được thụt vào hoàn toàn nhất quán, nhưng vẫn hấp dẫn. Nếu bạn cần giải pháp linh hoạt/nhất quán hơn, bạn chỉ có thể sửa đổi lớp học.

Tìm chức năng tô điểm và sửa đổi nó như vậy (nó nằm trong lớp Tag trong element.py):

#Add the myTab keyword to the functions parameters (or whatever you want to call it), set it to your preferred default. 
def prettify(self, encoding=None, formatter="minimal", myTab=2): 
    Tag.myTab= myTab # add a reference to it in the Tag class 
    if encoding is None: 
     return self.decode(True, formatter=formatter) 
    else: 
     return self.encode(encoding, True, formatter=formatter) 

Và sau đó di chuyển đến các phương pháp giải mã trong lớp Tag và làm như sau thay đổi:

if pretty_print: 
    #space = (' ' * (indent_level - 1)) 
    space = (' ' * (indent_level - Tag.myTab)) 
    #indent_contents = indent_level + Tag.myTab 
    indent_contents = indent_level + Tag.myTab 

Sau đó đi đến phương pháp decode_contents trong lớp Tag và làm cho những thay đổi này:

#s.append(" " * (indent_level - 1)) 
s.append(" " * (indent_level - Tag.myTab)) 
.210

Bây giờ BeautifulSoup ('< gốc > <con> <desc> chữ </desc > </con > </root >') .prettify (myTab = 4) sẽ trở lại:

<root> 
    <child> 
     <desc> 
      Text 
     </desc> 
    </child> 
</root> 

** Không cần phải vá lớp BeautifulSoup vì nó kế thừa lớp Tag. Patching Tag class là đủ, đủ để đạt được mục tiêu.

+0

Điều này sẽ rất dễ dàng để chuyển đổi thành một bản vá chống lại cây nguồn bs4, tiện dụng. OP chỉ có thể làm cho ngã ba của riêng mình của cây bzr và vá nó, gửi các bản vá thượng nguồn, vv – abarnert

+0

Cảm ơn guys. Tôi chỉ không thể tin rằng chỉ có một người có vấn đề với điều này trong những năm này và đề xuất một bản vá, và nó vẫn chưa được sáp nhập. Tôi đã sửa đổi các chức năng để có chiều dài biến (như tôi ghét cứng mã hóa những thứ). Nó khá nhiều những gì bạn đã gợi ý. Nhưng vấn đề là bạn cần phải cung cấp một cái gì đó cho 'indent_level' vì dòng này' pretty_print = (indent_level không phải là None) 'Và như tôi thấy giá trị mặc định của' indent_level' là 'None' và không có cách nào thay đổi động nó. <_ < –

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