0

概要

私は現在、このページにあるサイト用のパーサーを作成しようとしています。

私はすでにXPath(私はかなり得意です)を試しましたが、期待した結果を達成しようとして惨めに失敗したので、昨日から正規表現を使用しようとしています.

私の目標

ここでの私の目標は、この html をフラグメントに分割し、各フラグメントに 1 つのコースのデータを含めることです。

例:"AF - Bacharelado em Artes Visuais"はコース名で、科目は まで青いテーブルで見つけることができます08º Semestre: 24 Créditos

その後"AG - Licenciatura em Artes - Artes Visuais"、新しいコースの開始である などが表示されます。

このページには 2 つのコースしかありませんが、`このページには 2 つ以上のコースがあります。

正規表現の問題

私の友人が私に手を差し伸べてくれて、このパターンとオプションを使用すると、コースの名前に到達するのに役立つことがわかりました. ここにいくつかのコードがあります:

// Creating Regular Expression to find name of courses
Regex regex = new Regex ("<p><br><b><font face=\"Arial,Helvetica\"><font color=\"#000099\"><font size=-1>(.+?)</font></font></font></b>", RegexOptions.Singleline);

int startIndex = 0;
while (regex.IsMatch (auxHtml, startIndex))
    {
        // Checking name of the course and saving it's offset
        int index         = regex.Match(auxHtml, startIndex).Groups[1].Index;
        string courseName = regex.Match(auxHtml, startIndex).Groups[1].Value;
    } 

問題

コースの名前とそのオフセット (インデックス) に到達できるので、理論的には、Html を分割して、それぞれが 1 つのコースに関連するデータだけを含むようにすることができます。

ここに私がそれを試すために使用しているコードがあります。

  • htmlPages は文字列のリストです
  • auxHtml は、WebRequest によって取得された HtmlPage です。

コード

// Creating Regular Expression to find name of courses
Regex regex = new Regex ("<p><br><b><font face=\"Arial,Helvetica\"><font color=\"#000099\"><font size=-1>(.+?)</font></font></font></b>", RegexOptions.Singleline);

int startIndex = 0;
while (regex.IsMatch (auxHtml, startIndex))
{
    // Checking name of the course and saving it's offset
    int index         = regex.Match(auxHtml, startIndex).Groups[1].Index;
    string courseName = regex.Match(auxHtml, startIndex).Groups[1].Value;

    // Adding name of the course and offset to dictionary
    courseIndex.Add (courseName,index);
    startIndex        = regex.Match(auxHtml, startIndex).Groups[1].Index;

    // Splitting HTML Page
    if (regex.IsMatch(auxHtml, startIndex))
    {
        int endIndex = regex.Match (auxHtml, startIndex).Groups[1].Index;
        endIndex  = endIndex - startIndex;
        htmlPiece = auxHtml.Remove(startIndex, endIndex);
    }

    htmlPages.Add(auxHtml);
}

理由はわかりませんが、インデックスがめちゃくちゃです。

2 番目のコース名のインデックスは 8022 ですが、試してみると、

auxHtml.Substring(0,8022) 

次のコースの名前の前で終わる html の一部が表示されます。

ここで何が欠けていますか?

この「インデックス」属性は、HTML ページのパターンの開始のインデックスであるグループの「インデックス」属性ではありませんか?

4

4 に答える 4

5

RegEx(s) を使用して探しているものをほぼ達成できるかもしれませんが、それは難しいに違いありません。

正規表現は、この仕事に適したツールではありません。XML パーサーを使用して HTML を解析する方がはるかに優れています。これは、HTML (および一般的な XML) マークアップが正規の言語ではないためです。この場合、正規表現はあまり役に立ちません。

System.Xml.XmlDocument クラスを確認する必要があります。

于 2012-07-27T14:11:17.670 に答える
4

HTMLの解析に正規表現を使用しないでください。真の正規表現はそれができず、拡張正規表現はそれに適していません。HTMLを処理するには、既存の解析ライブラリを使用する必要があります。自分で処理する必要がある場合は、正規言語ではなく、文脈自由言語に基づいてソリューションを作成する必要があります。

于 2012-07-27T14:11:53.707 に答える
3

HTMLに正規表現を使用しないでください。代わりにHtmlAgilityPackを使用して、HtmlでXPathを使用できるようにしてください。

問題は、HTMLが適切に動作する言語ではなく、正規表現が解析するにはルールに例外が多すぎることです。この問題を解決するために特別に作成されたHtmlAgilityPackのようなライブラリ。

于 2012-07-27T14:12:08.857 に答える
1

この場合、正規表現は示されていませんでしたが、それを使用して問題を解決できました。

コードが巨大なので、コードをコピーしませんが、何をしたかを説明します。

この正規表現を使用して、コース名を見つけました

Regex regex = new Regex ("<p><br><b><font face=\"Arial,Helvetica\"><font   color=\"#000099\"><font size=-1>(.+?)</font></font></font></b>", RegexOptions.Singleline);`

その後、各コース名のオフセットを見つけることができました

各コース名のオフセットをフェッチしたら、Html をセグメントに分割しました。セグメントの開始はコース名の直前のオフセットであり、終了は次のコース名の直前のオフセット、またはファイルの末尾です。コースの場合は、html の最後のコースになります。

興味のある方のために、これが私の実装のコードです

これが、整形式でない html を解析しようとしている私のような人々に役立つことを願っています。

さて、正規表現はこのタスクを実行できないと言った人のために、少し時間をかけて私のコードを読んでください。気が変わるかもしれません。

于 2012-07-27T19:10:35.353 に答える