Python을 사용하여 HTML 파일에서 텍스트 추출
Python을 사용하여 HTML 파일에서 텍스트를 추출하고 싶습니다.기본적으로 브라우저에서 텍스트를 복사하여 메모장에 붙여넣을 때와 같은 출력을 원합니다.
HTML에서 실패할 수 있는 정규 표현식보다 더 강력한 표현을 사용하고 싶습니다. 많은 사람들이 아름다운 수프를 추천하는 것을 봐왔지만, 사용하는 데 몇 가지 문제가 있었습니다.하나는 자바스크립트 소스와 같은 원치 않는 텍스트를 집어 들었다.또한 HTML 엔티티를 해석하지 않았습니다.예를 들어 HTML 소스의 '는 브라우저 콘텐츠를 메모장에 붙여넣은 것처럼 텍스트의 아포스트로피로 변환됩니다.
html2text
망해보보 보보보다다HTML 자바스크립트그러나 일반 텍스트가 정확히 생성되지는 않습니다. 마크다운이 생성되므로 일반 텍스트로 변환해야 합니다.예시나 설명서는 포함되어 있지 않지만 코드는 깨끗합니다.
관련 질문:
javascript나 원하지 않는 것을 얻지 않고 텍스트를 추출하기 위해 찾은 최고의 코드:
from urllib.request import urlopen
from bs4 import BeautifulSoup
url = "http://news.bbc.co.uk/2/hi/health/2284783.stm"
html = urlopen(url).read()
soup = BeautifulSoup(html, features="html.parser")
# kill all script and style elements
for script in soup(["script", "style"]):
script.extract() # rip it out
# get text
text = soup.get_text()
# break into lines and remove leading and trailing space on each
lines = (line.strip() for line in text.splitlines())
# break multi-headlines into a line each
chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
# drop blank lines
text = '\n'.join(chunk for chunk in chunks if chunk)
print(text)
BeautifulSoup을 설치하기 전에 다음과 같이 하십시오.
pip install beautifulsoup4
html2text는 Python 프로그램으로 이 작업을 상당히 잘합니다.
주의: NTLK는 더 이상 지원하지 않습니다.clean_html
아래의 답변과 댓글 섹션의 다른 답변입니다.
NLTK 사용
html2text 문제를 데4했습니다.NLTK로 하다
그것은 마법처럼 작동한다.
import nltk
from urllib import urlopen
url = "http://news.bbc.co.uk/2/hi/health/2284783.stm"
html = urlopen(url).read()
raw = nltk.clean_html(html)
print(raw)
오늘도 똑같은 문제에 봉착한 자신을 발견했어요.모든 마크업에서 들어오는 콘텐츠를 삭제하고, 나머지 텍스트는 최소한의 포맷으로 되돌리기 위해 매우 간단한 HTML 파서를 작성했습니다.
from HTMLParser import HTMLParser
from re import sub
from sys import stderr
from traceback import print_exc
class _DeHTMLParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.__text = []
def handle_data(self, data):
text = data.strip()
if len(text) > 0:
text = sub('[ \t\r\n]+', ' ', text)
self.__text.append(text + ' ')
def handle_starttag(self, tag, attrs):
if tag == 'p':
self.__text.append('\n\n')
elif tag == 'br':
self.__text.append('\n')
def handle_startendtag(self, tag, attrs):
if tag == 'br':
self.__text.append('\n\n')
def text(self):
return ''.join(self.__text).strip()
def dehtml(text):
try:
parser = _DeHTMLParser()
parser.feed(text)
parser.close()
return parser.text()
except:
print_exc(file=stderr)
return text
def main():
text = r'''
<html>
<body>
<b>Project:</b> DeHTML<br>
<b>Description</b>:<br>
This small script is intended to allow conversion from HTML markup to
plain text.
</body>
</html>
'''
print(dehtml(text))
if __name__ == '__main__':
main()
이미 많은 해답이 있다는 것을 알지만, 제가 찾은 가장 우아하고 비호적인 해답은 부분적으로 여기에 설명되어 있습니다.
from bs4 import BeautifulSoup
text = ' '.join(BeautifulSoup(some_html_string, "html.parser").findAll(text=True))
갱신하다
Fraser의 코멘트에 근거해, 보다 우아한 솔루션을 소개합니다.
from bs4 import BeautifulSoup
clean_text = ' '.join(BeautifulSoup(some_html_string, "html.parser").stripped_strings)
여기 조금 더 완벽한 xperroni의 답변 버전이 있습니다.스크립트 및 스타일 섹션을 건너뛰고 문자(예: ') 및 HTML 도면요소(예: &)를 변환합니다.
또한 단순한 플레인텍스트에서HTML 역변환기를 포함합니다.
"""
HTML <-> text conversions.
"""
from HTMLParser import HTMLParser, HTMLParseError
from htmlentitydefs import name2codepoint
import re
class _HTMLToText(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self._buf = []
self.hide_output = False
def handle_starttag(self, tag, attrs):
if tag in ('p', 'br') and not self.hide_output:
self._buf.append('\n')
elif tag in ('script', 'style'):
self.hide_output = True
def handle_startendtag(self, tag, attrs):
if tag == 'br':
self._buf.append('\n')
def handle_endtag(self, tag):
if tag == 'p':
self._buf.append('\n')
elif tag in ('script', 'style'):
self.hide_output = False
def handle_data(self, text):
if text and not self.hide_output:
self._buf.append(re.sub(r'\s+', ' ', text))
def handle_entityref(self, name):
if name in name2codepoint and not self.hide_output:
c = unichr(name2codepoint[name])
self._buf.append(c)
def handle_charref(self, name):
if not self.hide_output:
n = int(name[1:], 16) if name.startswith('x') else int(name)
self._buf.append(unichr(n))
def get_text(self):
return re.sub(r' +', ' ', ''.join(self._buf))
def html_to_text(html):
"""
Given a piece of HTML, return the plain text it contains.
This handles entities and char refs, but not javascript and stylesheets.
"""
parser = _HTMLToText()
try:
parser.feed(html)
parser.close()
except HTMLParseError:
pass
return parser.get_text()
def text_to_html(text):
"""
Convert the given text to html, wrapping what looks like URLs with <a> tags,
converting newlines to <br> tags and converting confusing chars into html
entities.
"""
def f(mo):
t = mo.group()
if len(t) == 1:
return {'&':'&', "'":''', '"':'"', '<':'<', '>':'>'}.get(t)
return '<a href="%s">%s</a>' % (t, t)
return re.sub(r'https?://[^] ()"\';]+|[&\'"<>]', f, text)
스트립그램 라이브러리에서 html2text 메서드를 사용할 수도 있습니다.
from stripogram import html2text
text = html2text(your_html_string)
스트립그램을 설치하려면 sudo easy_install 스트립그램을 실행합니다.
여기에 이미 많은 답이 있다는 것을 알지만, 신문 3000도 언급할 가치가 있다고 생각합니다.저는 최근에 웹상의 기사에서 텍스트를 추출하는 유사한 작업을 완료해야 했고, 이 라이브러리는 지금까지 제 테스트에서 이것을 훌륭하게 해냈습니다.메뉴 항목 및 사이드바에 있는 텍스트와 OP 요청으로 페이지에 표시되는 JavaScript는 무시됩니다.
from newspaper import Article
article = Article(url)
article.download()
article.parse()
article.text
HTML 파일을 이미 다운로드 받은 경우 다음과 같은 작업을 수행할 수 있습니다.
article = Article('')
article.set_html(html)
article.parse()
article.text
기사 토픽을 요약하기 위한 몇 가지 NLP 기능도 갖추고 있습니다.
article.nlp()
article.summary
데이터 마이닝을 위한 패턴 라이브러리가 있습니다.
http://www.clips.ua.ac.be/pages/pattern-web
보관할 태그도 결정할 수 있습니다.
s = URL('http://www.clips.ua.ac.be').download()
s = plaintext(s, keep={'h1':[], 'h2':[], 'strong':[], 'a':['href']})
print s
더 빠르고 더 낮은 정확도가 필요한 경우 raw lxml을 사용할 수 있습니다.
import lxml.html as lh
from lxml.html.clean import clean_html
def lxml_to_text(html):
doc = lh.fromstring(html)
doc = clean_html(doc)
return doc.text_content()
PyParsing은 일을 잘 한다.PyParsing Wiki가 죽었기 때문에 PyParsing을 사용한 예가 여기에 있습니다(링크 예시).파싱에 약간의 시간을 투자해야 하는 이유 중 하나는 그가 매우 간략하게 잘 정리된 O'Reilly Short Cut 매뉴얼을 썼기 때문입니다. 이 매뉴얼도 저렴합니다.
하지만 저는 BeautifulSoup을 많이 사용하고 있기 때문에 엔티티 문제에 대처하는 것은 어렵지 않습니다.BeautifulSoup을 실행하기 전에 변환할 수 있습니다.
행운을 빌어요
이것은 정확히 Python 솔루션은 아니지만 Javascript가 생성하는 텍스트를 텍스트로 변환합니다(예: google.com).브라우저 링크(Lynx 아님)에는 Javascript 엔진이 있으며 -dump 옵션을 사용하여 소스를 텍스트로 변환합니다.
따라서 다음과 같은 작업을 수행할 수 있습니다.
fname = os.tmpnam()
fname.write(html_source)
proc = subprocess.Popen(['links', '-dump', fname],
stdout=subprocess.PIPE,
stderr=open('/dev/null','w'))
text = proc.stdout.read()
HTMLParser 모듈 대신 htmlib를 확인합니다.비슷한 인터페이스를 가지고 있지만, 더 많은 작업을 할 수 있습니다.(오래된 것이기 때문에 javascript나 css를 없애는 것은 큰 도움이 되지 않습니다.파생 클래스를 만들 수 있지만 start_script 및 end_style과 같은 이름의 메서드를 추가할 수 있습니다(자세한 내용은 python 문서를 참조하십시오). 그러나 잘못된 형식의 html에 대해서는 이를 확실하게 수행하기 어렵습니다).어쨌든, 여기 일반 텍스트를 콘솔에 출력할 수 있는 간단한 것이 있습니다.
from htmllib import HTMLParser, HTMLParseError
from formatter import AbstractFormatter, DumbWriter
p = HTMLParser(AbstractFormatter(DumbWriter()))
try: p.feed('hello<br>there'); p.close() #calling close is not usually needed, but let's play it safe
except HTMLParseError: print ':(' #the html is badly malformed (or you found a bug)
구스 추출기 구스라고 불리는 Python 패키지는 다음 정보를 추출할 것을 권장합니다.
기사 본문 기사 본문 기사 본문 기사 메타 설명 메타 태그에 포함된 Youtube/Vimeo 동영상
기타 : https://pypi.python.org/pypi/goose-extractor/
설치, html2text 사용
pip install html2text
그리고나서,
>>> import html2text
>>>
>>> h = html2text.HTML2Text()
>>> # Ignore converting links from HTML
>>> h.ignore_links = True
>>> print h.handle("<p>Hello, <a href='http://earth.google.com/'>world</a>!")
Hello, world!
아름다운 수프는 html 엔티티를 변환합니다.HTML은 종종 버그가 있고 유니코드 및 HTML 인코딩 문제로 가득 찬다는 것을 고려하면 아마도 가장 좋은 선택일 것입니다.html을 raw 텍스트로 변환하기 위해 사용하는 코드는 다음과 같습니다.
import BeautifulSoup
def getsoup(data, to_unicode=False):
data = data.replace(" ", " ")
# Fixes for bad markup I've seen in the wild. Remove if not applicable.
masssage_bad_comments = [
(re.compile('<!-([^-])'), lambda match: '<!--' + match.group(1)),
(re.compile('<!WWWAnswer T[=\w\d\s]*>'), lambda match: '<!--' + match.group(0) + '-->'),
]
myNewMassage = copy.copy(BeautifulSoup.BeautifulSoup.MARKUP_MASSAGE)
myNewMassage.extend(masssage_bad_comments)
return BeautifulSoup.BeautifulSoup(data, markupMassage=myNewMassage,
convertEntities=BeautifulSoup.BeautifulSoup.ALL_ENTITIES
if to_unicode else None)
remove_html = lambda c: getsoup(c, to_unicode=True).getText(separator=u' ') if c else ""
또 다른 비피톤 솔루션: Libre Office:
soffice --headless --invisible --convert-to txt input1.html
제가 다른 대안보다 이것을 선호하는 이유는 HTML의 모든 단락이 하나의 텍스트 행으로 변환되기 때문입니다(줄 바꿈 없이). 그것이 제가 찾고 있었습니다.다른 방법은 후처리가 필요합니다.링스는 생산량은 좋지만, 내가 찾던 것은 아니다.게다가 Libre Office는 모든 종류의 포맷에서 변환할 수 있습니다.
나 시도해 본 이 있다bleach.clean(html,tags=[],strip=True)
표백제로요?나한테는 효과가 있어요
내게 가장 좋은 것은 대본이다.
https://github.com/weblyzard/inscriptis
import urllib.request
from inscriptis import get_text
url = "http://www.informationscience.ch"
html = urllib.request.urlopen(url).read().decode('utf-8')
text = get_text(html)
print(text)
결과는 정말 좋다.
저도 비슷한 질문이 있었는데 사실 뷰티풀 수프 중에 하나를 사용했어요.문제는 그게 너무 느리다는 거야.저는 셀렉스라는 도서관을 사용하게 되었습니다.상당히 제한적이지만 이 작업에는 효과가 있습니다.유일한 문제는 불필요한 공백을 수동으로 제거했다는 것입니다.하지만 BeautifulSoup 솔루션이 훨씬 더 빨리 작동하는 것 같습니다.
from selectolax.parser import HTMLParser
def get_text_selectolax(html):
tree = HTMLParser(html)
if tree.body is None:
return None
for tag in tree.css('script'):
tag.decompose()
for tag in tree.css('style'):
tag.decompose()
text = tree.body.text(separator='')
text = " ".join(text.split()) # this will remove all the whitespaces
return text
다른 옵션은 텍스트 기반 웹 브라우저를 통해 html을 실행하고 덤프하는 것입니다.예: (Lynx 사용):
lynx -dump html_to_convert.html > converted_html.txt
이는 다음과 같이 python 스크립트 내에서 수행할 수 있습니다.
import subprocess
with open('converted_html.txt', 'w') as outputFile:
subprocess.call(['lynx', '-dump', 'html_to_convert.html'], stdout=testFile)
HTML 파일의 텍스트만 제공하는 것은 아니지만 사용 사례에 따라서는 html2text 출력보다 더 좋을 수 있습니다.
PeYoTIL은 BeautifulSoup을 사용하여 스타일과 스크립트 내용을 배제하는 답변은 나에게 맞지 않았다. 제가 한번 써봤어요.decompose
extract
예요.이렇게 해서 도 같이 만들었는데<p>
및 치환 " " "<a>
태그를 지정합니다.또, 텍스트내의 링크에 대응합니다.테스트 문서가 포함된 이 Gest에서 입수할 수 있습니다.
from bs4 import BeautifulSoup, NavigableString
def html_to_text(html):
"Creates a formatted text email message as a string from a rendered html template (page)"
soup = BeautifulSoup(html, 'html.parser')
# Ignore anything in head
body, text = soup.body, []
for element in body.descendants:
# We use type and not isinstance since comments, cdata, etc are subclasses that we don't want
if type(element) == NavigableString:
# We use the assumption that other tags can't be inside a script or style
if element.parent.name in ('script', 'style'):
continue
# remove any multiple and leading/trailing whitespace
string = ' '.join(element.string.split())
if string:
if element.parent.name == 'a':
a_tag = element.parent
# replace link text with the link
string = a_tag['href']
# concatenate with any non-empty immediately previous string
if ( type(a_tag.previous_sibling) == NavigableString and
a_tag.previous_sibling.string.strip() ):
text[-1] = text[-1] + ' ' + string
continue
elif element.previous_sibling and element.previous_sibling.name == 'a':
text[-1] = text[-1] + ' ' + string
continue
elif element.parent.name == 'p':
# Add extra paragraph formatting newline
string = '\n' + string
text += [string]
doc = '\n'.join(text)
return doc
아파치 티카에게 좋은 결과를 얻었습니다.콘텐츠에서 메타데이터와 텍스트를 추출하는 것이 목적이기 때문에 기본 파서는 그에 따라 즉시 튜닝됩니다.
Tika는 서버로 실행할 수 있으며 Docker 컨테이너에서 실행/전개가 간단하며 Python 바인딩을 통해 액세스할 수 있습니다.
간단한 방법으로
import re
html_text = open('html_file.html').read()
text_filtered = re.sub(r'<(.*?)>', '', html_text)
이 코드는 '<'로 시작하여 '>'로 끝나는 html_text의 모든 부분을 찾아 빈 문자열로 모두 바꿉니다.
Python 3.x에서는 'imaplib' 및 'email' 패키지를 Import하여 매우 쉽게 실행할 수 있습니다.오래된 게시물이긴 하지만 제 답변이 이 게시물에 새로 오신 분들에게 도움이 될 것 같습니다.
status, data = self.imap.fetch(num, '(RFC822)')
email_msg = email.message_from_bytes(data[0][1])
#email.message_from_string(data[0][1])
#If message is multi part we only want the text version of the body, this walks the message and gets the body.
if email_msg.is_multipart():
for part in email_msg.walk():
if part.get_content_type() == "text/plain":
body = part.get_payload(decode=True) #to control automatic email-style MIME decoding (e.g., Base64, uuencode, quoted-printable)
body = body.decode()
elif part.get_content_type() == "text/html":
continue
이제 본문 변수를 인쇄할 수 있으며, 일반 텍스트 형식으로 출력할 수 있습니다. :) 적절한 경우 수락된 답변으로 선택하는 것이 좋습니다.
여기 제가 평소에 사용하는 코드가 있습니다.
from bs4 import BeautifulSoup
import urllib.request
def processText(webpage):
# EMPTY LIST TO STORE PROCESSED TEXT
proc_text = []
try:
news_open = urllib.request.urlopen(webpage.group())
news_soup = BeautifulSoup(news_open, "lxml")
news_para = news_soup.find_all("p", text = True)
for item in news_para:
# SPLIT WORDS, JOIN WORDS TO REMOVE EXTRA SPACES
para_text = (' ').join((item.text).split())
# COMBINE LINES/PARAGRAPHS INTO A LIST
proc_text.append(para_text)
except urllib.error.HTTPError:
pass
return proc_text
도움이 됐으면 좋겠어요.
BeautifulSoup으로 HTML에서 텍스트만 추출할 수 있습니다.
url = "https://www.geeksforgeeks.org/extracting-email-addresses-using-regular-expressions-python/"
con = urlopen(url).read()
soup = BeautifulSoup(con,'html.parser')
texts = soup.get_text()
print(texts)
많은 사람들이 html 태그를 제거하기 위해 regex를 사용하는 것을 언급했지만, 많은 단점이 있다.
예를 들어 다음과 같습니다.
<p>hello world</p>I love you
구문 분석 대상:
Hello world
I love you
여기 제가 생각해낸 조각이 있습니다. 당신은 그것을 당신의 특정한 요구에 맞출 수 있습니다. 그리고 그것은 마법처럼 작동합니다.
import re
import html
def html2text(htm):
ret = html.unescape(htm)
ret = ret.translate({
8209: ord('-'),
8220: ord('"'),
8221: ord('"'),
160: ord(' '),
})
ret = re.sub(r"\s", " ", ret, flags = re.MULTILINE)
ret = re.sub("<br>|<br />|</p>|</div>|</h\d>", "\n", ret, flags = re.IGNORECASE)
ret = re.sub('<.*?>', ' ', ret, flags=re.DOTALL)
ret = re.sub(r" +", " ", ret)
return ret
Python 2.7.9+에서 BeautifulSoup4를 사용하는 또 다른 예
에는 다음이 포함됩니다.
import urllib2
from bs4 import BeautifulSoup
코드:
def read_website_to_text(url):
page = urllib2.urlopen(url)
soup = BeautifulSoup(page, 'html.parser')
for script in soup(["script", "style"]):
script.extract()
text = soup.get_text()
lines = (line.strip() for line in text.splitlines())
chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
text = '\n'.join(chunk for chunk in chunks if chunk)
return str(text.encode('utf-8'))
설명:
URL 데이터를 html로 읽고(BeautifulSoup 사용), 스크립트 요소와 스타일 요소를 모두 삭제하고 .get_text()를 사용하여 텍스트만 가져옵니다.행으로 분할하여 각각 선행 및 후행 공백을 제거한 다음 각 청크 =(line의 경우 phrase.strip(), line의 경우 phrase.strip(""))로 분할합니다.그런 다음 텍스트 = '\n'.displaces를 사용하여 빈 줄을 삭제한 후 마지막으로 승인된 utf-8로 돌아갑니다.
주의:
이 시스템이 실행되고 있는 일부 시스템에서는 SSL 문제로 인해 https:// 연결이 실패합니다. 이 문제를 해결하려면 확인을 해제할 수 있습니다.수정 예: http://blog.pengyifan.com/how-to-fix-python-ssl-certificate_verify_failed/
Python < 2 . 7 . 9 에서는, 이것을 실행하는 것에 문제가 있을 가능성이 있습니다.
text.tftutf-8')는 이상한 인코딩을 남길 수 있으며 대신 str(text)만 반환할 수 있습니다.
저는 이렇게 하고 있어요.
>>> import requests
>>> url = "http://news.bbc.co.uk/2/hi/health/2284783.stm"
>>> res = requests.get(url)
>>> text = res.text
언급URL : https://stackoverflow.com/questions/328356/extracting-text-from-html-file-using-python
'source' 카테고리의 다른 글
Python의 상대 경로 (0) | 2022.12.18 |
---|---|
PHP 네임스페이스를 자동 로드와 함께 사용하려면 어떻게 해야 합니까? (0) | 2022.12.18 |
최대 절전 모드에서 결과 집합을 추출할 수 없습니다. (0) | 2022.12.18 |
HashTables는 충돌에 어떻게 대처합니까? (0) | 2022.12.18 |
레코드를 단일 레코드로 선택하여 시간 차이를 확인하는 방법 (0) | 2022.12.18 |