Что бы я использовал, чтобы удалить экранированный HTML из больших наборов данных - PullRequest
6 голосов
/ 13 апреля 2010

Наша база данных заполнена статьями, полученными из RSS-каналов. Я не был уверен в том, какие данные я получу, и сколько фильтрации уже настроено (плагин WP-O-Matic Wordpress с использованием библиотеки SimplePie). Этот плагин выполняет некоторую базовую кодировку перед вставкой, используя встроенную функцию пост-вставки Wordpress, которая также выполняет некоторую фильтрацию. Между кодировкой RSS-канала, кодировкой плагина с использованием PHP, кодировкой Wordpress и экранированием SQL, я не уверен, с чего начать.

Данные обычно находятся в конце поля после содержимого, которое я хочу сохранить. Это все в одной строке, но выделены для удобства чтения:

<img src="http://feeds.feedburner.com/~ff/SoundOnTheSound?i=xFxEpT2Add0:xFbIkwGc-fk:V_sGLiPBpWU" border="0"></img>

<img src="http://feeds.feedburner.com/~ff/SoundOnTheSound?d=qj6IDK7rITs" border="0"></img>

&lt;img src=&quot;http://feeds.feedburner.com/~ff/SoundOnTheSound?i=xFxEpT2Add0:xFbIkwGc-fk:D7DqB2pKExk&quot;

Обратите внимание, что некоторые изображения сбежали, а некоторые нет. Я полагаю, что это связано с тем, что последняя часть была обрезана, чтобы ее нельзя было распознать как HTML-тег, что привело к тому, что он был HTML-кодом с конечным кодированием, в то время как фактические теги img остались одни.

В другой записи только это в одном из полей, что означает, что RSS-лента ничего не дала мне за элемент (отфильтровано сейчас, но у меня есть несколько таких записей):

&lt;img src=&quot;http://farm3.static.flickr.com/2183/2289902369_1d95bcdb85.jpg&quot; alt=&quot;post_img&quot; width=&quot;80&quot;

Все извлеченные образцы находятся в одной строке , но разбиты для удобства чтения. В противном случае они копируются точно из базы данных из командной строки mysql client.

Вопрос: Каков наилучший способ работы с вышеуказанным экранированным html (или частью html-тега), поэтому я могу удалить его , не затрагивая содержимое?

Я хочу удалить его, потому что изображения в конце поля обычно являются изображениями, которые не имеют никакого отношения к контенту. В случае с механизмами подачи, FeedBurner добавляет их к каждому отдельному продукту в канале. В других случаях это неработающие ссылки, окружающие неработающие изображения. Дело не в правильных тегах html img, которые можно легко удалить. Это искаженные теги, которые, если они не закодированы, не будут действительными html, которые не будут обрабатываться вашими стандартными html-парсерами.

[EDIT] Если бы это был всего лишь вопрос получения нужного мне html-кода и выполнения strip_tags и повторной вставки данных, я бы не задавал этот вопрос.

Часть, с которой у меня есть проблема, заключается в том, что то, что раньше было тегом img, было закодировано в формате html, а конец обрезан. Если он декодирован, он будет , а не тегом html, поэтому я не могу разобрать его обычным способом.

Со всем этим &lt;img src=&quot; дерьмом, я не могу заставить себя искать его, кроме SELECT ID, post_content FROM table WHERE post_content LIKE '&lt;img', который, по крайней мере, получает мне эти посты. Но когда я получаю данные, мне нужен способ их найти, удалить, но сохранить остальное содержимое.

[/ EDIT]

[РЕДАКТИРОВАТЬ 2]

<img src="http://farm4.static.flickr.com/3162/2735565872_b8a4e4bd17.jpg" alt="post_img" width="80" />Through the first two months of the year, the volume of cargo handled at Port of Portland terminals has increased 46 percent as the port?s marine cargo business shows signs of recovering from a dismal 2009.<div> <a href="http://feeds.bizjournals.com/~ff/bizj_portland?a=YIs66yw13JE:_zirAnH6dt8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/bizj_portland?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.bizjournals.com/~ff/bizj_portland?a=YIs66yw13JE:_zirAnH6dt8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/bizj_portland?i=YIs66yw13JE:_zirAnH6dt8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.bizjournals.com/~ff/bizj_portland?a=YIs66yw13JE:_zirAnH6dt8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/bizj_portland?i=YIs66yw13JE:_zirAnH6dt8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.bizjournals.com/~ff/bizj_portland?a=YIs66yw13JE:_zirAnH6dt8:qj6IDK7rITs">&lt;img src=&quot;http://feeds.feedburner.com/~ff/bizj_portland?d=qj6IDK7rITs&quot;

Часть, которую я хочу сохранить:

<img src="http://farm4.static.flickr.com/3162/2735565872_b8a4e4bd17.jpg" alt="post_img" width="80" />Through the first two months of the year, the volume of cargo handled at Port of Portland terminals has increased 46 percent as the port?s marine cargo business shows signs of recovering from a dismal 2009.

Повторюсь: речь идет не об удалении допустимых тегов html img. Это легко. Мне нужно быть в состоянии найти, в частности, &lt;img src=&quot;http://feeds.feedburner.com/~ff/bizj_portland?d=qj6IDK7rITs&quot;, если он является частью шаблона тега img, искаженного тега img или якоря img anchor img img искалеченного изображения и т. Д., И т. Д., Но not remove &lt;img if это действительно часть статьи. Из нескольких дюжин сэмплов, которые я просмотрел, было довольно непротиворечиво, что этот искаженный тег img находится в конце поля.

Еще один тег с одним искаженным изображением. Это постоянно искаженный тег flickr img, но, как и выше, я не могу просто найти &lt;img, поскольку он может быть допустимой частью содержимого.

Проблема заключается в том, что я не могу просто декодировать и анализировать его как HTML, потому что он не будет действительным html. [/ EDIT 2]

Ответы [ 6 ]

3 голосов
/ 13 апреля 2010

Лучший способ:

  1. Установите HTML :: Entities из CPAN и используйте его для удаления URI.
  2. Установите HTML :: Parser из CPAN и используйте его для анализа и удаления URI после их удаления.

Регулярные выражения не подходят для этой задачи.

2 голосов
/ 14 апреля 2010

Вопрос обновлен ...

Чтобы извлечь нужные данные, вы можете использовать этот подход:

use HTML::Entities qw/decode_entities/;

my $decoded = decode_entities $raw;

if ($decoded =~ s{ (<img .+? (?:>.+?</img>|/>)) } {}x) {  # grab the image
    my $img = $1;
    $decoded =~ s{<.+?>}      {}xg;  # strip complete tags
    $decoded =~ s{< [^>]+? $} {}x;   # strip trailing noise

    print $img.$decoded;
}

Использование регулярного выражения для анализа HTML обычно не одобряется, однако в данном случае речь идет скорее об удалении сегментов, соответствующих шаблону. После тестирования регулярных выражений на большем наборе данных у вас должно быть представление о том, что может потребоваться настроить.

Надеюсь, это поможет.

2 голосов
/ 14 апреля 2010

Я бы не раздевался. Это далеко от невосстановимого барахла.

Сначала примените HTML::Entities::decode_entities условно (используйте в качестве первого символа эвристический <), затем позвольте HTML::Tidy::libXML->clean(…, 'UTF-8', 1) восстановить разметку, как предполагалось. clean возвращает весь документ, но просто извлечь необходимый элемент img.

0 голосов
/ 14 апреля 2010

Учитывая пример ввода и вывода, который вы дадите в конце вашего поста, следующее даст вам желаемый результат:

#!/usr/bin/perl

use strict; use warnings;

use HTML::TokeParser::Simple;
my $parser = HTML::TokeParser::Simple->new( \*DATA );

if ( my $tag = $parser->get_tag('img') ) {
    print $tag->as_is;
    print $parser->get_text('div');
}

__DATA__
<img src="http://farm4.static.flickr.com/3162/2735565872_b8a4e4bd17.jpg" alt="post_img" width="80" />Through the first two months of the year, the volume of cargo handled at Port of Portland terminals has increased 46 percent as the port?s marine cargo business shows signs of recovering from a dismal 2009.<div> <a href="http://feeds.bizjournals.com/~ff/bizj_portland?a=YIs66yw13JE:_zirAnH6dt8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/bizj_portland?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.bizjournals.com/~ff/bizj_portland?a=YIs66yw13JE:_zirAnH6dt8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/bizj_portland?i=YIs66yw13JE:_zirAnH6dt8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.bizjournals.com/~ff/bizj_portland?a=YIs66yw13JE:_zirAnH6dt8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/bizj_portland?i=YIs66yw13JE:_zirAnH6dt8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.bizjournals.com/~ff/bizj_portland?a=YIs66yw13JE:_zirAnH6dt8:qj6IDK7rITs">&lt;img src=&quot;http://feeds.feedburner.com/~ff/bizj_portland?d=qj6IDK7rITs&quot;

Выход:

<img src="http://farm4.static.flickr.com/3162/2735565872_b8a4e4bd17.jpg" alt="po st_img" width="80" />Through the first two months of the year, the volume of car go handled at Port of Portland terminals has increased 46 percent as the port?s marine cargo business shows signs of recovering from a dismal 2009.

Однако я озадачен размером и объемом каждого куска, который вы должны обрабатывать.

0 голосов
/ 14 апреля 2010

Лучше всего будет вспомнить все статьи в базе данных, чтобы они не были обрезаны и не повреждены. Если это не вариант, то ...

Исходя из ваших примеров выше, похоже, что вы убираете все, что следует за текстовым содержанием каждой статьи. В вашем примере за текстовым содержимым следует тег DIV и набор тегов IMG, которые могли или не могли быть усечены или преобразованы в объекты HTML.

Если все ваши записи похожи, вы можете удалить все после текстового содержимого, удалив последний тег div и все, что следует за ним, используя perl, например:

my $article = magic_to_get_an_article();
$article =~ s/<div>.*//s;
magic_to_store_article($article);

Если в ваших записях есть что-то более сложное, чем это, вам лучше воспользоваться модулем парсинга HTML и внимательно прочитать документацию, чтобы узнать, как он обрабатывает недопустимый HTML.

0 голосов
/ 13 апреля 2010

Как насчет глупого простого Perl-поиска и замены в переменной, содержащей ваши данные ...

foreach $line(@lines) {
    $line =~ s/&lt;/</gi;
    $line =~ s/&gt;/>/gi;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...