파이썬 문자열로 HTML 엔터티를 디코딩 하시겠습니까?


266

Beautiful Soup 3으로 일부 HTML을 구문 분석하고 있지만 Beautiful Soup 3에서 자동으로 디코딩하지 않는 HTML 엔티티가 포함되어 있습니다.

>>> from BeautifulSoup import BeautifulSoup

>>> soup = BeautifulSoup("<p>&pound;682m</p>")
>>> text = soup.find("p").string

>>> print text
&pound;682m

어떻게에서 HTML 엔티티 디코딩 할 수 text얻는 "£682m"대신을 "&pound;682m".


답변:


521

파이썬 3.4+

사용 html.unescape():

import html
print(html.unescape('&pound;682m'))

FYI html.parser.HTMLParser.unescape는 더 이상 사용되지 않으며 실수로 남아 있지만 3.5 에서 제거되어야합니다 . 언어에서 곧 제거 될 것입니다.


파이썬 2.6-3.3

HTMLParser.unescape()표준 라이브러리에서 사용할 수 있습니다 .

>>> try:
...     # Python 2.6-2.7 
...     from HTMLParser import HTMLParser
... except ImportError:
...     # Python 3
...     from html.parser import HTMLParser
... 
>>> h = HTMLParser()
>>> print(h.unescape('&pound;682m'))
£682m

six호환성 라이브러리를 사용하여 가져 오기를 단순화 할 수도 있습니다 .

>>> from six.moves.html_parser import HTMLParser
>>> h = HTMLParser()
>>> print(h.unescape('&pound;682m'))
£682m

9
이 방법은 "& # 8217;"과 같은 문자를 이스케이프하지 않는 것 같습니다. python2.6에서 로컬로 작동하지만 Google 앱 엔진에서. 여전히 엔터티 (예 : & quot;)를 최소한 디코딩합니다
gfxmonk

문서화되지 않은 API는 어떻게 더 이상 사용되지 않을 수 있습니까? 답변을 수정했습니다.
Markus Unterwaditzer 2016 년

@MarkusUnterwaditzer 문서화되지 않은 메소드를 더 이상 사용하지 않을 이유가 없습니다. 이 경우 지원 중단 경고가 표시됩니다. 답변 수정을 참조하십시오.
Mark Amery

unescape방법 이 아니라 전체 HTMLParser모듈이 더 이상 사용되지 않는 것이 더 논리적으로 보입니다 html.parser.
Tom Russell

파이썬 2에 주목할 가치가 있습니다 : 특수 문자는 라틴 -1 (ISO-8859-1) 인코딩 대응 문자로 대체됩니다. 예를 들어, 필요할 수 있습니다 h.unescape(s).encode("utf-8"). 문서 : "" "여기에 제공된 정의에는 XHTML 1.0에 의해 정의 된 라틴어 1 문자 세트 (ISO-8859-1)에서 간단한 텍스트 대체를 사용하여 처리 할 수있는 모든 엔티티가 포함되어 있습니다." ""
익명 겁쟁이

65

뷰티플 수프는 개체 변환을 처리합니다. Beautiful Soup 3에서는 다음을 지정해야합니다.convertEntitiesBeautifulSoup 생성자에 인수 ( 보관 된 문서 의 '엔티티 변환' 섹션 참조 ). Beautiful Soup 4에서는 엔티티가 자동으로 디코딩됩니다.

아름다운 수프 3

>>> from BeautifulSoup import BeautifulSoup
>>> BeautifulSoup("<p>&pound;682m</p>", 
...               convertEntities=BeautifulSoup.HTML_ENTITIES)
<p682m</p>

아름다운 수프 4

>>> from bs4 import BeautifulSoup
>>> BeautifulSoup("<p>&pound;682m</p>")
<html><body><p682m</p></body></html>

+1. 내가 문서에서 이것을 놓친 방법을 모르겠습니다. 정보 주셔서 감사합니다. 나는 luc의 대답을 받아 들일 것입니다. 왜냐하면 그는 질문에 지정한 표준 라이브러리 (나에게 중요하지 않음)와 다른 사람들에게 더 일반적으로 사용되기 때문입니다.
jkp

5
BeautifulSoup4주로을 사용합니다 HTMLParser. 출처
scharfmn

4
원본 문자열에 포함되지 않은 외부 HTML을 모두 사용하지 않고 Beautiful Soup 4에서 어떻게 변환 할 수 있습니까? (예 : <html> 및 <body>)
Praxiteles

@Praxiteles : BeautifulSoup ( '& pound; 682m', "html.parser") stackoverflow.com/a/14822344/4376342
Soitje

13

w3lib.html 라이브러리에서 replace_entities를 사용할 수 있습니다

In [202]: from w3lib.html import replace_entities

In [203]: replace_entities("&pound;682m")
Out[203]: u'\xa3682m'

In [204]: print replace_entities("&pound;682m")
£682m

2

Beautiful Soup 4를 사용하면 포맷터를 출력 으로 설정할 수 있습니다

를 전달 formatter=None하면 Beautiful Soup은 출력시 문자열을 전혀 수정하지 않습니다. 가장 빠른 옵션이지만 다음 예제와 같이 Beautiful Soup에서 잘못된 HTML / XML을 생성 할 수 있습니다.

print(soup.prettify(formatter=None))
# <html>
#  <body>
#   <p>
#    Il a dit <<Sacré bleu!>>
#   </p>
#  </body>
# </html>

link_soup = BeautifulSoup('<a href="http://example.com/?foo=val1&bar=val2">A link</a>')
print(link_soup.a.encode(formatter=None))
# <a href="http://example.com/?foo=val1&bar=val2">A link</a>

이것은 질문에 대답하지 않습니다. (또한 HTML의 마지막 비트에 대해서는 문서가 무엇을 말하는지 잘 모르겠습니다.)
Mark Amery

<< Sacré bleu! >>는 <및>를 이스케이프 처리하지 않아 HTML을 깨뜨릴 수없는 잘못된 부분입니다. 나는 이것이 나로부터 늦은 게시물이라는 것을 알고 있지만, 누군가
가보고

0

비슷한 인코딩 문제가있었습니다. normalize () 메서드를 사용했습니다. 내 데이터 프레임을 다른 디렉토리의 .html 파일로 내보낼 때 pandas .to_html () 메소드를 사용하여 유니 코드 오류가 발생했습니다. 나는 이것을 끝내고 효과가 있었다 ...

    import unicodedata 

데이터 프레임 객체는 원하는대로 할 수 있습니다. 테이블이라고 부릅니다.

    table = pd.DataFrame(data,columns=['Name','Team','OVR / POT'])
    table.index+= 1

테이블 데이터를 인코딩하여 템플릿 폴더의 .html 파일로 내보낼 수 있습니다 (원하는 위치에 관계없이 가능)

     #this is where the magic happens
     html_data=unicodedata.normalize('NFKD',table.to_html()).encode('ascii','ignore')

정규화 된 문자열을 HTML 파일로 내보내기

    file = open("templates/home.html","w") 

    file.write(html_data) 

    file.close() 

참조 : 유니 코드 데이터 문서


-4

이것은 아마도 여기에 관련이 없습니다. 그러나 전체 문서에서 이러한 HTML entites를 제거하려면 다음과 같이 할 수 있습니다. 이).

import re
import HTMLParser

regexp = "&.+?;" 
list_of_html = re.findall(regexp, page) #finds all html entites in page
for e in list_of_html:
    h = HTMLParser.HTMLParser()
    unescaped = h.unescape(e) #finds the unescaped value of the html entity
    page = page.replace(e, unescaped) #replaces html entity with unescaped value

7
아니! HTML 엔터티를 직접 일치시킬 필요는 없습니다. 당신.unescape()위해 그것을 않습니다 . 수락 된 답변에 이미 .unescape()문자열에서 엔터티를 찾을 수 있음을 명확하게 표시했을 때 자신과 엔터티 일치를 롤링하는이 복잡한 솔루션을 게시 한 이유를 이해하지 못합니다 .
Mark Amery
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.