20

私の質問はこの質問のようなものですが、さらに制約があります:

  • 私は文書がかなり正気であることを知っています
  • それらは非常に規則的です(それらはすべて同じソースから来ました
  • 表示されるテキストの約 99% が必要です
  • 実行可能なものの約 99% はテキストです (それらは多かれ少なかれ HTML に変換された RTF です)。
  • 書式設定や段落の区切りも気にしません。

これを行うために設定されたツールはありますか、それとも RegexBuddy と C# を分解したほうがよいでしょうか?

コマンド ラインやバッチ処理ツール、C/C#/D ライブラリにオープンです。

4

9 に答える 9

22

HTML Agility Packで今日ハッキングしたこのコードは、フォーマットされていないトリミングされたテキストを抽出します。

public static string ExtractText(string html)
{
    if (html == null)
    {
        throw new ArgumentNullException("html");
    }

    HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(html);

    var chunks = new List<string>(); 

    foreach (var item in doc.DocumentNode.DescendantNodesAndSelf())
    {
        if (item.NodeType == HtmlNodeType.Text)
        {
            if (item.InnerText.Trim() != "")
            {
                chunks.Add(item.InnerText.Trim());
            }
        }
    }
    return String.Join(" ", chunks);
}

ある程度の書式設定を維持したい場合は、ソースで提供されているサンプルに基づいて作成できます。

public string Convert(string path)
{
    HtmlDocument doc = new HtmlDocument();
    doc.Load(path);

    StringWriter sw = new StringWriter();
    ConvertTo(doc.DocumentNode, sw);
    sw.Flush();
    return sw.ToString();
}

public string ConvertHtml(string html)
{
    HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(html);

    StringWriter sw = new StringWriter();
    ConvertTo(doc.DocumentNode, sw);
    sw.Flush();
    return sw.ToString();
}

public void ConvertTo(HtmlNode node, TextWriter outText)
{
    string html;
    switch (node.NodeType)
    {
        case HtmlNodeType.Comment:
            // don't output comments
            break;

        case HtmlNodeType.Document:
            ConvertContentTo(node, outText);
            break;

        case HtmlNodeType.Text:
            // script and style must not be output
            string parentName = node.ParentNode.Name;
            if ((parentName == "script") || (parentName == "style"))
                break;

            // get text
            html = ((HtmlTextNode) node).Text;

            // is it in fact a special closing node output as text?
            if (HtmlNode.IsOverlappedClosingElement(html))
                break;

            // check the text is meaningful and not a bunch of whitespaces
            if (html.Trim().Length > 0)
            {
                outText.Write(HtmlEntity.DeEntitize(html));
            }
            break;

        case HtmlNodeType.Element:
            switch (node.Name)
            {
                case "p":
                    // treat paragraphs as crlf
                    outText.Write("\r\n");
                    break;
            }

            if (node.HasChildNodes)
            {
                ConvertContentTo(node, outText);
            }
            break;
    }
}


private void ConvertContentTo(HtmlNode node, TextWriter outText)
{
    foreach (HtmlNode subnode in node.ChildNodes)
    {
        ConvertTo(subnode, outText);
    }
}
于 2012-05-10T03:09:35.197 に答える
8

HTMLAgilityPackを使用する必要があります。

おそらく、LINQ antDescendants呼び出しを使用して要素を検索し、その要素を取得する必要がありInnerTextます。

于 2010-01-21T23:08:00.807 に答える
5

私が使用しているコードは次のとおりです。

using System.Web;
public static string ExtractText(string html)
{
    Regex reg = new Regex("<[^>]+>", RegexOptions.IgnoreCase);
    string s =reg.Replace(html, " ");
    s = HttpUtility.HtmlDecode(s);
    return s;
}
于 2015-04-08T19:13:39.723 に答える
3

最良の方法は次のとおりです。

  public static string StripHTML(string HTMLText)
    {
        Regex reg = new Regex("<[^>]+>", RegexOptions.IgnoreCase);
        return reg.Replace(HTMLText, "");
    }
于 2012-11-19T17:07:38.870 に答える
2

HTMLをC#にロードし、mshtml.dllまたはC#/ WinFormsのWebBrowserコントロールを使用すると、HTMLドキュメント全体をツリーとして扱い、InnerTextオブジェクトをキャプチャするツリーをトラバースできます。

または、document.allを使用することもできます。これは、ツリーを取得してフラット化し、ツリー全体を反復処理して、再びInnerTextをキャプチャします。

次に例を示します。

        WebBrowser webBrowser = new WebBrowser();
        webBrowser.Url = new Uri("url_of_file"); //can be remote or local
        webBrowser.DocumentCompleted += delegate
        {
            HtmlElementCollection collection = webBrowser.Document.All;
            List<string> contents = new List<string>();

            /*
             * Adds all inner-text of a tag, including inner-text of sub-tags
             * ie. <html><body><a>test</a><b>test 2</b></body></html> would do:
             * "test test 2" when collection[i] == <html>
             * "test test 2" when collection[i] == <body>
             * "test" when collection[i] == <a>
             * "test 2" when collection[i] == <b>
             */
            for (int i = 0; i < collection.Count; i++)
            {
                if (!string.IsNullOrEmpty(collection[i].InnerText))
                {
                    contents.Add(collection[i].InnerText);
                }
            }

            /*
             * <html><body><a>test</a><b>test 2</b></body></html>
             * outputs: test test 2|test test 2|test|test 2
             */
            string contentString = string.Join("|", contents.ToArray());
            MessageBox.Show(contentString);
        };

お役に立てば幸いです。

于 2010-01-21T23:12:49.587 に答える
1

ここでは、HTML と XAML を相互に変換するツールとそのソースをダウンロードできます: XAML/HTML コンバーター

これには HTML パーサーが含まれており (そのようなものは、標準の XML パーサーよりもはるかに寛容でなければなりません)、XML とほぼ同じように HTML をトラバースできます。

于 2010-01-22T16:03:15.073 に答える