Perl HTML::TagParser를 사용하여 느슨한 HTML을 구문 분석하십시오.

16982 단어 Perl

HTML 파서 이것



HTML은 인간이 텍스트 에디터로 손에 넣은 것이 대부분으로, 태그의 닫는 것을 잊거나 닫는 장소가 어긋나거나 하는 일이 많이 있습니다. 마늘의 물건 ( '-`)
그러나 브라우저는 그런 느슨한 소스에서도 가능한 한 최선을 다해 표시하십시오. 좋은 아이군요.

이런 닫는 것을 잊어도 건강하게 표시해주는 브라우저 씨
<div>
<ul>
    <li>メニュー1</li>
    <li>メニュー2</li>
    <li>メニュー3</li>
</div>

Perl에서 HTML을 분해하려고 CPAN을 잡으면 XML::ParserHTML::Parser 등 여러 종류가 있습니다.
하지만 하지만! 이 아이들은 너무 스토킹하고 태그 오류를 발견하면 거기서 포기하는 아이가 대부분입니다.
위와 같은 소스를 읽으면 "나는 이미 포기했다"라고 한마디 토하고 그 이상은 읽어 주지 않습니다.

HTML::TagParser



거기서 고상하게 나타난 것은 HTML::TagParser씨.
무려 이 아이는, 어떤 더러운 HTML이라도 포기하지 않고 끝까지 읽어 주는 미남입니다. (그리고 메이드 인 재팬)



네이티브 자바 스크립트와 함께 매우 편리!



사용 예
use HTML::TagParser;

#読み込む
my $html = HTML::TagParser->new('http://www.abcd.com');

#エレメントを抽出
$html->getElementById('content1');

#子エレメントを取得
my @childs = @{$element->childNodes()};

#子エレメントのDIVタグのinnerTextを書き出してみる
foreach my $elm (@childs){
    if($elm->tagName() eq "div"){
        print $elm->innerText(),"\n";
    }
}

좀 더 사용하기 쉽습니다!



웹은 비슷한 페이지라도 서버 측에서 일부가 누락되어 있거나와 패턴을 결정하는 것은 꽤 어렵다. 그 때마다 판별의 소스를 쓰는 것도 조금 힘들다.

그래서 일단, 일단 스칼라 변수에 읽어 버려서.

스칼라화 함수
# ---------------------------------------------------------------------------
# 引数: $element:     HTML::TagParser か HTML::TagParser::Element
#       $flag:        子要素が $flag 未満の場合、innerTextを取得。省略時は取得しない。
sub Eelement2Scalar {
    my ($element, $flag) = @_;
    my $ret = {};

    # HTML::TagParserをそのまま放り込まれた時の処理
    if($element && ref($element) ne 'HTML::TagParser::Element' && $element->can("getElementsByTagName")){
        $element = $element->getElementsByTagName('html');
    }

    # tag
    if($element && $element->can("tagName")){
        my $tag = $element->tagName();
        return $ret if($tag !~ /^\w+/); #scriptタグ内でナマモノ見つけた時の回避処理
        $ret->{'tag'} = $tag;
    }

    # attr
    if($element && $element->can("attributes")){
        my $attr = $element->attributes();
        $ret->{'attr'} = $attr if($attr && scalar(%{$attr}) > 0);
    }

    # childs
    my @childs = ();
    if($element && $element->can("childNodes")){
        @childs = @{$element->childNodes()};
        foreach my $elm (@childs){
            push @{$ret->{'childs'}}, Eelement2Scalar($elm, $flag);
        }
    }

    # text
    if($flag && scalar(@childs)<=$flag && $element && $element->can("innerText")){
        $ret->{'text'} = $element->innerText();
    }
    return $ret;
}

사용 예
use HTML::TagParser;
#use LWP::Simple;
use Data::Dumper;{package Data::Dumper;sub qquote{return shift;}}$Data::Dumper::Useperl=1;
use Encode;

my $file = sjis("どっかから拾った.html");
my $doc = load_file($file);

## LWP::Simple を使う例
#my $url = "http://www.abcd.com";
#my $doc = get($url);

#IDを指定してエレメントを取得
my $html = HTML::TagParser->new($doc)->getElementById("content_block_2");

#スカラー化
my $child_scalar = Eelement2Scalar($html, 0);

#ダンプ表示
print Dumper $child_scalar;

#ファイル読み込み用
sub load_file {
    my $file = shift;
    my $ret = "";
    if (-e $file) {
        open (my $FILE, "<$file") or die;
        $ret = do { local $/; <$FILE> };
        close($FILE);
    }
    return $ret;
}

#テスト環境はActivePerlなのでファイル名をSJISに変換
sub sjis {
    my ($val) = shift;
    $val = decode_utf8($val) if (!Encode::is_utf8($val));
    return Encode::encode('ms932', $val);
}

출력 결과의 예
{
  'tag' => 'td',
  'childs' => [
                {
                  'childs' => [
                                {
                                  'attr' => {
                                              'class' => 'fsize',
                                              'style' => 'font-size:13px;'
                                            },
                                  'tag' => 'span'
                                }
                              ],
                  'tag' => 'div',
                  'attr' => {
                              'style' => 'text-align:left;'
                            }
                }
              ]
}

결론



최근 브라우저의 자바스크립트는 동일 도메인 외부에서 ajax로 html을 취득하는 것을 금지하게 되었으므로, 아직 이런 HTML 파서가 활약할 기회도 있을 것 같습니다.
서버 측에서 할 경우, Node.js를 두드리는 것이 더 편할지도 모르지만, Perl을 아직 활약하고 싶다면 꼭 시도하십시오.

좋은 웹페이지 즐겨찾기