1

いくつかのhtmlファイルを少し掘り下げる必要があり、最初にそれらを1行に1タグずつツリーの読み取り可能な形式に変換したいと思いました。それにもかかわらず、私はhtmlの経験がありません。誰かが私のコードを訂正して、私が忘れたルールを指摘してもらえますか?

私のコードは実際のページでは機能しません。プログラムの実行の最後に、ネストカウンターを0に設定する必要があります。これは、プログラムが出会ったすべてのネストされたタグを残す必要があるためです。そうではありません。Facebookページの場合、2000を超えるタグが開いたままになっています。

ライブラリの使用を提案する前に、私はそこに良いライブラリを見たことがありません。私のページでは、xmlへの変換がどういうわけか失敗し、htmlcxxライブラリに適切なドキュメントがありません。

#include <cstdio>

char get_char( FILE *stream ) {
    char c;
    do
        c = getc(stream);
    while ( c == ' ' || c == '\n' || c == '\t' || c == '\r' );
    return c;
}

void fun( FILE *stream, FILE *out ) {   
    int counter = -1;
    char c;

    do {
        c = get_char(stream);
        if ( c == EOF )
            break;

        if ( c != '<' ) { // print text
            for ( int i = counter + 1; i; --i )
                putc( ' ', out );
            fprintf( out, "TEXT: " );
            do {
                if ( c == '\n' )
                    fprintf( out, "<BR>" ); // random separator
                else
                    putc( c, out );
                c = getc( stream );
            } while ( c != '<' );
            putc( '\n', out );
        }

        c = getc( stream );
        if ( c != '/' ) { // nest deeper
            ++counter;
            for ( int i = counter; i; --i )
                putc( ' ', out );
        } else { // go back in nesting
            --counter;
            // maybe here should be some exception handling
            do // assuming there's no strings in quotation marks here
                c = getc( stream );
            while ( c != '>' );
            continue;
        }

        ungetc( c, stream );
        do { // reading tag
            c = getc(stream);
            if( c == '/' ) { // checking if it's not a <blahblah/>
                c = getc(stream);
                if ( c == '>' ) {
                    --counter;
                    break;
                }
                putc( '/', out );
                putc( c, out );
            } else if ( c == '"' ) { // not parsing strings put in quotation marks
                do {
                    putc( c, out ); c = getc( stream );
                    if ( c == '\\' ) {
                        putc( c, out ); c = getc( stream );
                        if ( c == '"' ) {
                            putc( c, out ); c = getc( stream );
                        }
                    }
                } while ( c != '"' );
                putc( c, out );
            } else if ( c == '>' ) { // end of tag
                break;
            } else // standard procedure
                putc( c, out );
        } while ( true );
        putc( '\n', out );
    } while (true);
    fprintf( out, "Counter: %d", counter );
}

int main() {
    const char *name = "rfb.html";
    const char *oname = "out.txt";
    FILE *file = fopen(name, "r");
    FILE *out = fopen(oname, "w");
    fun( file, out );
    return 0;
}
4

2 に答える 2

1

HTML != XML タグは閉じていない可能性があります。たとえば、<img ...>等しいと見なされます<img ... />

于 2013-02-22T12:44:57.503 に答える
0

そのような興味深く有用なトピックとほとんど答えはありません。本当に奇妙です...

優れた C++ HTML パーサーを見つけるのは難しい! 私は正しい方向に導くようにしています...それはあなたが先に進むのを助けるかもしれません...

Lib curl ページには、作業を開始するためのソース コードが含まれています。dom ツリーをトラバースするドキュメント。xml パーサーは必要ありません。不適切な形式の html でも失敗しません。

http://curl.haxx.se/libcurl/c/htmltidy.html

別のオプションは htmlcxx です。ウェブサイトの説明から:

htmlcxx は、C++ 用の単純な非検証 css1 および html パーサーです。

tidyHTML のようなライブラリを試すことができます - http://tidy.sourceforge.net (無料)

Qt 4.6 を使用している場合は、QWebElement を使用できます。簡単な例:

フレーム->setHtml(HTML); QWebElement document = frame->documentElement(); QList imgs = document.findAll("img"); 別の例を次に示します。http://doc.qt.digia.com/4.6/webkit-simpleselector.html

于 2013-02-23T12:56:53.557 に答える