7

BeautifulSoupを使用してWebページからテキストを取得しようとしています。

以下は私がそうするために書いたスクリプトです。2つの引数を取ります。1つは入力HTMLまたはXMLファイル、2つ目は出力ファイルです。

import sys
from bs4 import BeautifulSoup

def stripTags(s): return BeautifulSoup(s).get_text()

def stripTagsFromFile(inFile, outFile):
    open(outFile, 'w').write(stripTags(open(inFile).read()).encode("utf-8"))

def main(argv):
    if len(sys.argv) <> 3:
        print 'Usage:\t\t', sys.argv[0], 'input.html output.txt'
        return 1
    stripTagsFromFile(sys.argv[1], sys.argv[2])
    return 0

if __name__ == "__main__":
    sys.exit(main(sys.argv))

残念ながら、多くのWebページでは、たとえば次のようになります。http ://www.greatjobsinteaching.co.uk/career/134112/Education-Manager-Location 次のようなものが表示されます(最初の行は数行しか表示されていません)。

html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    Education Manager  Job In London With  Caleeda | Great Jobs In Teaching

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-15255540-21']);
_gaq.push(['_trackPageview']);
_gaq.push(['_trackPageLoadTime']);

スクリプトに何か問題がありますか?BeautifulSoupのコンストラクターの2番目の引数として「xml」と「html5lib」および「lxml」を渡そうとしましたが、役に立ちません。このタスクに適したBeautifulSoupの代替品はありますか?私が欲しいのは、このWebページのブラウザでレンダリングされるテキストを抽出することだけです。

どんな助けでも大歓迎です。

4

3 に答える 3

14

nltk'sclean_html()はこれがかなり得意です!

あなたがすでにあなたのhtmlを次のhtmlような変数に保存していると仮定します

html = urllib.urlopen(address).read()

その後、使用するだけ

import nltk
clean_text = nltk.clean_html(html)

アップデート

nltkの将来のバージョンでは、サポートが削除されclean_htmlます。clean_url今のところBeautifulSoupを使用してください...それは非常に残念です。

これを実現する方法の例は、次のページにあります。

BeatifulSoup4get_textにはまだjavascriptがあります

于 2012-11-14T19:48:38.470 に答える
2

ここでの答えに基づくアプローチは次のとおりです。jbochiによるBeautifulSoupGrabVisibleWebpageText。このアプローチでは、ページテキストを含む要素にコメントを埋め込むことができ、改行を削除したり、スペースを統合したりすることで、出力をクリーンアップすることができます。

html = urllib.urlopen(address).read()
soup = BeautifulSoup.BeautifulSoup(html)
texts = soup.findAll(text=True)

def visible_text(element):
    if element.parent.name in ['style', 'script', '[document]', 'head', 'title']:
        return ''
    result = re.sub('<!--.*-->|\r|\n', '', str(element), flags=re.DOTALL)
    result = re.sub('\s{2,}|&nbsp;', ' ', result)
    return result

visible_elements = [visible_text(elem) for elem in texts]
visible_text = ''.join(visible_elements)
print(visible_text)
于 2012-05-10T22:58:00.707 に答える
2

これが私が抱えていた問題でした。テキスト(Webブラウザで実際にレンダリングされるテキスト)を返すことができるソリューションはないようです。他のソリューションでは、BSはレンダリングに理想的ではなく、html2textが優れたアプローチであると述べています。私はhtml2textとnltk.clean_htmlの両方を試しましたが、タイミングの結果に驚いたので、後世のための答えが必要だと思いました。もちろん、速度の差はデータの内容に大きく依存する可能性があります...

@Helgeからのここでの1つの答えは、すべてのもののnltkを使用することについてでした。

import nltk

%timeit nltk.clean_html(html)
was returning 153 us per loop

レンダリングされたhtmlで文字列を返すことは本当にうまくいきました。このnltkモジュールは、html2textよりも高速でしたが、おそらくhtml2textの方が堅牢です。

betterHTML = html.decode(errors='ignore')
%timeit html2text.html2text(betterHTML)
%3.09 ms per loop
于 2013-11-05T17:48:52.277 に答える