Форум: "Начинающим";
Текущий архив: 2012.05.27;
Скачать: [xml.tar.bz2];
ВнизУдаление тегов из ХТМЛ-страницы Найти похожие ветки
← →
Pcrepair © (2012-01-18 20:47) [0]Добрый день
есть код:
var
Form1: TForm1;
HTML : ustring;
//////////////////////////////////
procedure TForm1.Button1Click(Sender: TObject);
var
URL : string;
begin
URL := Edit1.Text;
Chromium1.Browser.MainFrame.LoadUrl(URL);
end;
procedure TForm1.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; httpStatusCode: Integer; out Result: Boolean);
begin
if (httpStatusCode <> 200) then Exit;
Memo1.Clear;
Chromium1.Browser.MainFrame.VisitDomProc(
procedure(const Dom: ICefDomDocument)
begin
HTML := Dom.Document.AsMarkup;
end );
Memo1.Clear;
Memo1.Lines.Add(HTML);
end;
end.
Код закачивает страницу с заданным УРЛ, производит обработку скриптов и размещает код страницы в ПЕРЕМ типа ustring
Все работает.
Далее необходимо переработать код в ПЕРЕМ ХТМЛ. В частности нужно удалить все теги типа <script..мусор...>..мусор...</script>, <style type=..мусор>...мусор...</style> и прочие такие же, типа ( ), не содержащие информации. в общем нужно радикально зачистить страницу, оставив только теги ссылок <a href= " ">...........</a> и теги таблиц <TR></TR>, чтоб ни рекламы. ни флеша, ни картинок
ВОПРОС:
каким способом это лучше сделать? может есть каки то проверенные способы уже
может есть какие то модули типа TParser? или типа того
Всем ответившим по делу - спасибо
← →
Dennis I. Komarov © (2012-01-18 21:55) [1]Pos[Ex](
← →
KilkennyCat © (2012-01-19 03:16) [2]Pos вряд ли эффективно...
тут проще пробежаться побайтово, накапливая и сравнивая. то есть, бежим, читаем байт, тут же пишем в новый текст. как только встречаем < начинаем в отдельную переменую копить, до ближайшего пробела, в новый текст не пишем. анализируем полученное, если ненужный тэг - бежим дальше, проверяем /, после него проверяем > и алгоритм улетает в начало. если нужный тэг - переменную добавляем в новый текст, алгоритм улетает в начало. это в общих чертах, конечно, но я такое когда-то делал, примитивный парсер, довольно-таки просто и очень быстро. проверка / и > - тут надо повнимательней. ее не надо проверять, если тэг не встречен или нужен.
← →
int64 © (2012-01-19 06:33) [3]Видел библиотеку-конвертор из HTML в XHTML.
Задача сводится к работе с XML. Немного ресурсоемко, зато архитектурно прозрачно.
зы. Есть ощущение, что сабж не раз решался через регулярные выражения.
ззы. Откуда уверенность, что в <script..мусор...>..мусор...</script>, не будет нужного отображаемого контента?
← →
DVM © (2012-01-19 10:13) [4]Вот посмотри этот когда, я когда то писал машину состояний для разбора HTML. Не идеальна она конечно, но с моей задачей справлялась (замена всех URL на нужные мне). Класс TURLTransformer в данном случае тебе не нужен, как и функция TagHasUrl.
procedure ReplaceURLs(var S: string; ATransformer: TURLTransformer);
type
TState = (stStart, stDocType, stTag, stParam, stParamValue, stText, stComment);
var
State: TState;
i: integer;
TagName, ParamName, ParamValue: string;
Quotes, DQuotes: boolean;
S2: string;
procedure ProcessTag;
begin
//
end;
procedure ProcessParam;
begin
//
end;
procedure ProcessParamValue;
begin
if TagHasUrl(TagName, ParamName) then
ATransformer.TransformURL(ParamValue);
S2 := S2 + "="" + ParamValue + """;
end;
begin
Quotes := False;
DQuotes := False;
S2 := "";
State := stStart;
for i := 1 to Length(S) do
begin
case State of
stStart:
case S[i] of
"<":
begin
State := stTag;
TagName := "";
end;
end;
stDocType:
case S[i] of
">": State := stStart;
end;
stTag:
case S[i] of
"!":
if TagName = "" then
begin
if S[I+1] = "-" then
State := stComment
else
State := stDocType;
end;
" ", #9, #13, #10:
if TagName <> "" then
begin
ProcessTag;
State := stParam;
ParamName := "";
end;
">":
begin
ProcessTag;
State := stStart;
end;
"/":
if S[i + 1] = ">" then
begin
ProcessTag;
State := stStart;
end
else
TagName := TagName + S[i];
else
TagName := TagName + S[i];
end;
stParam:
case S[i] of
" ", #9, #13, #10:
;
"=":
if ParamName <> "" then
begin
State := stParamValue;
ProcessParam;
ParamValue := "";
Quotes := false;
DQuotes := false;
end;
">", "/":
begin
if ParamName <> "" then
ProcessParam;
State := stStart;
end;
else
ParamName := ParamName + S[i];
end;
stParamValue:
case S[i] of
"""":
if not DQuotes then
Quotes := not Quotes
else
ParamValue := ParamValue + S[i];
""":
if not Quotes then
DQuotes := not DQuotes
else
ParamValue := ParamValue + S[i];
" ", #9, #13, #10:
if Quotes or DQuotes then
ParamValue := ParamValue + S[i]
else
begin
ProcessParamValue;
State := stParam;
ParamName := "";
end;
"/":
if S[i + 1] = ">" then
begin
State := stStart;
ProcessParamValue;
end
else
ParamValue := ParamValue + S[i];
">":
begin
State := stStart;
ProcessParamValue;
end
else
ParamValue := ParamValue + S[i];
end;
stText:
;
stComment:
case S[i] of
"-":
if S[i + 1] = ">" then
State := stStart;
end;
end;
if State <> stParamValue then
S2 := S2 + S[i];
end;
S := S2;
end;
← →
DVM © (2012-01-19 10:16) [5]По аналогии [4] несложно переделать под замену/удаление/извлечение любых тегов и их параметров
← →
Pcrepair © (2012-01-19 15:10) [6]
> Откуда уверенность, что в <script..мусор...>..мусор...</script>,
> не будет нужного отображаемого контента?
уверенность есть, поскольку результаты работы скриптов уже есть в коде, загруженном в ПЕРЕМ. проверено.
>
> Есть ощущение, что сабж не раз решался через регулярные
> выражения.
конечно есть что такое уже, осталось найти и посмотреть
DVM, спасибо, будем пробовать
← →
Dimka Maslov © (2012-01-19 15:15) [7]
> ПЕРЕМ
п е р е м е н н а я
Запиши на большими буквами на бумаге и повесь на стену.
← →
Eraser © (2012-01-19 16:27) [8]> [0] Pcrepair © (18.01.12 20:47)
это тривиальная задача для любого php программера, решаемая с помощью регулярных выражений. Прикрути regexp.
← →
Pcrepair © (2012-01-19 21:32) [9]есть теория что использование pos/regexp может привести к непредсказуемым результатам, при обработке самых разных страниц (это будет поисковая программа)
← →
Eraser © (2012-01-19 22:25) [10]> [9] Pcrepair © (19.01.12 21:32)
кто автор теории? )
← →
Dimka Maslov © (2012-01-19 22:38) [11]есть теория, что использование таких вот программистов может привести к непредсказуемым результатам
← →
Dimka Maslov © (2012-01-19 22:48) [12]
> Eraser © (19.01.12 22:25) [10]
Мы уже узнали, что нет переменных есть только ПЕРЕМ, что читать MSDN и RFC бесполезно, что буфер обмена работает только на виртуальной машине, что нельзя использовать pos и regexp (как будто есть что-то другое). Но зато это будет поисковая программа! Круче чем гугл! Супер-пупер-мега-крутая. Вот только флудеры и теоретики мешают гению бездумно тырить код в этих ваших интернетах, а кроме того нагло отказываются писать за автора код... Тем более, что и в хромиуме наверняка есть свойства innerText и аnchors (или их аналоги), которые решают поставленную задачу мгновенно.
← →
DVM © (2012-01-19 22:54) [13]Имхо не тривиальная задача это и не для регулярных выражений. Только для выборки URL придется написать нехилое выражение. Например, надо не тупо выделять то, что начинается с http, а находить урлы, записанные самым экзотическим способом. Есть прорва тегов, которые могут содержать URL. Не надо реагировать на URL встречающиеся в тексте как текст и на те что внутри некоторых особых тегов.
Например, теги в которых может быть URL:
function TagHasUrl(const ATagName, ATagParam: string): Boolean;
var
Tag, Param: string;
begin
Tag := LowerCase(ATagName);
Param := LowerCase(ATagParam);
Result := ((Tag = "a") and (Param = "href")) or
((Tag = "applet") and (Param = "codebase")) or
((Tag = "applet") and (Param = "code")) or
((Tag = "applet") and (Param = "archive")) or
((Tag = "area") and (Param = "href")) or
((Tag = "bgsound") and (Param = "src")) or
((Tag = "blockquote") and (Param = "cite")) or
((Tag = "body") and (Param = "background")) or
((Tag = "del") and (Param = "cite")) or
((Tag = "embed") and (Param = "src")) or
((Tag = "frame") and (Param = "longdesc")) or
((Tag = "frame") and (Param = "src")) or
((Tag = "head") and (Param = "profile")) or
((Tag = "iframe") and (Param = "longdesc")) or
((Tag = "iframe") and (Param = "src")) or
((Tag = "ilayer") and (Param = "background")) or
((Tag = "ilayer") and (Param = "src")) or
((Tag = "img") and (Param = "longdesc")) or
((Tag = "img") and (Param = "src")) or
((Tag = "img") and (Param = "usemap")) or
((Tag = "img") and (Param = "dynsrc")) or
((Tag = "img") and (Param = "lowsrc")) or
((Tag = "input") and (Param = "src")) or
((Tag = "input") and (Param = "usemap")) or
((Tag = "input") and (Param = "dynsrc")) or
((Tag = "input") and (Param = "lowsrc")) or
((Tag = "ins") and (Param = "cite")) or
((Tag = "layer") and (Param = "background")) or
((Tag = "layer") and (Param = "src")) or
((Tag = "link") and (Param = "href")) or
((Tag = "link") and (Param = "href")) or
((Tag = "object") and (Param = "codebase")) or
((Tag = "object") and (Param = "classid")) or
((Tag = "object") and (Param = "data")) or
((Tag = "object") and (Param = "archive")) or
((Tag = "object") and (Param = "usemap")) or
((Tag = "q") and (Param = "cite")) or
((Tag = "script") and (Param = "src")) or
((Tag = "table") and (Param = "background")) or
((Tag = "td") and (Param = "background")) or
((Tag = "th") and (Param = "background")) or
((Tag = "xml") and (Param = "src")) or
((Tag = "base") and (Param = "href"));
end;
Это к моей задаче.
Задача автора вопроса не менее сложная, а то и более.
Мне кажется лучше всего будет произвести построение DOM модели чем то вот таким http://htmlp.sourceforge.net/ , фильтрация не нужных параметров и тегов и обратная сборка документа. Там есть пример подобного. Но с конечным автоматом быстрее конечно, но более трудоемко.
← →
DVM © (2012-01-19 23:02) [14]А на реальных страницах есть еще такая штука как не совсем корректный html, который тем не менее глотается браузерами.И это далеко не редкость. Почти любой крупный интернет ресурс изобилует ошибками в html. Если парсить по каким то заранее заданным правилам, то парсер может сработать неправильно. Ориентироваться надо по конкретной ситуации на странице иногда на ходу исправляя неверный код.
← →
DVM © (2012-01-19 23:06) [15]А для поисковика есть еще одна непростая задачка - комбинация базового и относительного урлов на странице для перехода паука. Это очень непростая задача. На сайте консорциума WWW есть специальные тесты для функций выполняющих комбинацию, практически ни один браузер не проходит их все.
Вот большинство из них:
TestCombineUrl("http://a/b/c/d;p?q", "g", "http://a/b/c/g");
TestCombineUrl("http://a/b/c/d;p?q", "./g", "http://a/b/c/g");
TestCombineUrl("http://a/b/c/d;p?q", "g/", "http://a/b/c/g/");
TestCombineUrl("http://a/b/c/d;p?q", "/g", "http://a/g");
TestCombineUrl("http://a/b/c/d;p?q", "//g", "http://g");
TestCombineUrl("http://a/b/c/d;p?q", "?y", "http://a/b/c/d;p?y");
TestCombineUrl("http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y");
TestCombineUrl("http://a/b/c/d;p?q", "#s", "http://a/b/c/d;p?q#s");
TestCombineUrl("http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s");
TestCombineUrl("http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s");
TestCombineUrl("http://a/b/c/d;p?q", ";x", "http://a/b/c/;x");
TestCombineUrl("http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x");
TestCombineUrl("http://a/b/c/d;p?q", "g;x?y#s", "http://a/b/c/g;x?y#s");
TestCombineUrl("http://a/b/c/d;p?q", ".", "http://a/b/c/");
TestCombineUrl("http://a/b/c/d;p?q", "./", "http://a/b/c/");
TestCombineUrl("http://a/b/c/d;p?q", "..", "http://a/b/");
TestCombineUrl("http://a/b/c/d;p?q", "../", "http://a/b/");
TestCombineUrl("http://a/b/c/d;p?q", "../g", "http://a/b/g");
TestCombineUrl("http://a/b/c/d;p?q", "../..", "http://a/");
TestCombineUrl("http://a/b/c/d;p?q", "../../", "http://a/");
TestCombineUrl("http://a/b/c/d;p?q", "../../g", "http://a/g");
TestCombineUrl("http://a/b/c/d;p?q", "../../../g", "http://a/g");
TestCombineUrl("http://a/b/c/d;p?q", "../../../../g", "http://a/g");
TestCombineUrl("http://a/b/c/d;p?q", "/./g", "http://a/g");
TestCombineUrl("http://a/b/c/d;p?q", "/../g", "http://a/g");
TestCombineUrl("http://a/b/c/d;p?q", "g.", "http://a/b/c/g.");
TestCombineUrl("http://a/b/c/d;p?q", ".g", "http://a/b/c/.g");
TestCombineUrl("http://a/b/c/d;p?q", "g..", "http://a/b/c/g..");
TestCombineUrl("http://a/b/c/d;p?q", "..g", "http://a/b/c/..g");
TestCombineUrl("http://a/b/c/d;p?q", "./../g", "http://a/b/g");
TestCombineUrl("http://a/b/c/d;p?q", "./g/.", "http://a/b/c/g/");
TestCombineUrl("http://a/b/c/d;p?q", "g/./h", "http://a/b/c/g/h");
TestCombineUrl("http://a/b/c/d;p?q", "g/../h", "http://a/b/c/h");
TestCombineUrl("http://a/b/c/d;p?q", "g;x=1/./y", "http://a/b/c/g;x=1/y");
TestCombineUrl("http://a/b/c/d;p?q", "g;x=1/../y", "http://a/b/c/y");
TestCombineUrl("http://a/b/c/d;p?q", "g?y/./x", "http://a/b/c/g?y/./x");
TestCombineUrl("http://a/b/c/d;p?q", "g?y/../x", "http://a/b/c/g?y/../x");
TestCombineUrl("http://a/b/c/d;p?q", "g#s/./x", "http://a/b/c/g#s/./x");
TestCombineUrl("http://a/b/c/d;p?q", "g#s/../x", "http://a/b/c/g#s/../x");
TestCombineUrl("http://a/b/c/d;p?q", "./g:h", "http://a/b/c/g:h");
TestCombineUrl("http://a/b/c/d;p?q", "http://a/b/c/g", "http://a/b/c/g");
TestCombineUrl("http://a", "/b/c/g", "http://a/b/c/g");
TestCombineUrl("a", "../b/c/g", "http://a/b/c/g");
TestCombineUrl("a", "./b/c/g", "http://a/b/c/g");
TestCombineUrl("a", "b/c/g", "http://a/b/c/g");
TestCombineUrl("", "a/b/c/g", "a/b/c/g") ;
TestCombineUrl("http://a/", "", "http://a/");
TestCombineUrl("http://a", "", "http://a/");
TestCombineUrl("", "", "");
← →
Pcrepair © (2012-01-20 16:07) [16]DVM, интересная информация, буду думать
с другой стороны речь идет об удалении ненужного.
например:
если написать циклический код, просматривающий все символы в ПЕРЕМ (код хтмл-страницы) и удаляющий конструкции типа то что между тегами не удаляется, это нужно, удаляются сами теги, как не несущие информации или <script..мусор...> вот тут все удаляется, ЖАБА код уже не нужен</script>
вроде проблем быть не должно? при обработке самых разных страниц. какой вариант предпочтительнее (pos или regexp) по критериям:
1. возможной глючности
2. скорости обработки (средняя страница 200 кб, ну 10 000 символов?)
3. сложности написания кода (regexp надо устанавливать в РАД, а pos это ведь "Работы со строками"?)
← →
Pcrepair © (2012-01-20 16:09) [17]глючит сервис
(б)
то что между тегами не удаляется, это нужно, удаляются сами теги, как не несущие информации(/б) - вот так правильно, имелся ввиду тег Б
← →
нонамэ (2012-01-21 00:21) [18]
> роде проблем быть не должно?
нет не должно, делай
← →
KilkennyCat © (2012-01-21 01:35) [19]Как народ любит регулярные выражения... я иногда их такие монструозные встречаю, что мне хочется или самому повеситься, или любителя того повесить.
> 3. сложности написания кода (regexp надо устанавливать в
> РАД, а pos это ведь "Работы со строками"?)
не нужен тут пос. долго будет, а простоты реализации не даст. DVM [4] - идеальное решение для данной задачи. и готовое почти.
← →
Eraser © (2012-01-21 19:29) [20]> [13] DVM © (19.01.12 22:54)
задача весьма тривиальна для preg_replace. года 4 назад я бы не задумываясь написал да выложил пример, но сейчас увы, у рег. выражений есть такое неприятное свойство, если не пользуешься ими - напрочь забываются )
автору рекомундую глянуть
http://php.net/manual/en/function.preg-replace.php и погуглить по запросу "preg_replace remove html tags"
← →
Eraser © (2012-01-21 19:37) [21]> [13] DVM © (19.01.12 22:54)
вся прелесть рег. выражений в том, что они настраиваются на определенные условия. для задачи определения url в любых тегах, задача сводится к следующему:
1. определяем, что текст находится внутри тэга.
2. по какием то определенным признакам определыем, что подстрока является url.
т.е. для наглядности можно даже не писать одно сложное выражение (хотя это возможно), а можно просто два раза вызвать функцию. первый раз выделяем все тэги (элементарная задача). второй раз выделяем url.
← →
DVM © (2012-01-21 21:36) [22]
> Eraser © (21.01.12 19:37) [21]
Облажаются регулярные выражения, споткнувшись о первую незакрытую кавычку на реальных страницах, готов спорить. Точнее сами по себе регулярные выражения не виноваты, но человек составляющий это выражение непременно что-то не учтет ибо нереально (хотя теоретически наверное возможно).
← →
DVM © (2012-01-21 22:25) [23]По сути регулярное выражение это ни что иное как общее описание работы конечного автомата аналогичного приведенному мной. При компиляции регулярного выражения движком как раз примерно такой код и будет построен.
Но платой за универсальность является меньшая их наглядность начиная с некоторого момента. Мне попадались регулярные выражения аж на 100 строк(!) Таким выражением например будет выражение выделяющее 99.9% всех валидных emal адресов в тексте (кто думает что в таком выражение от силы символов 50, тот сильно ошибается). Понять как работает такое выражение непросто даже писавшему его через некоторое время. Тем более модифицировать.
Другим моментом является скорость. Конечно все сильно зависит от конкретной реализации движка для работы с регулярными выражениями, но быстрее чем один проход по строке они точно быть не могут. Иногда это критично.
← →
Eraser © (2012-01-22 03:08) [24]> [22] DVM © (21.01.12 21:36)
насчет ковычек - одна из самых распространенных проблем, главное разработать правило, как работать со сбойными ковычками. соглашусь, что 100% вариантов предусмотреть не получится, но получится куда лучше и на порядки проще, чем писать конечный автомат вручную.
я разрабатывал типограф для одной известной cms в свое время, да, есть ряд сложностей, но все решаемо. при нынешних мощностях процессоров просчет даже сложнейших рег. выражений точно не узкое место.
← →
Eraser © (2012-01-22 03:13) [25]я вообще к чему веду. для задачи автора в интернетах наверняка можно нарыть ряд типовых и качественных решений написанных для preg_replace и работающих с удовлетворительным качеством. все можно найти адаптировать за пару-тройку часов и заниматься проектом дальше. для того, чтобы написать такое вручную, может потребоваться куда больше времени и в самый не подходящий момент могут (даже наверняка) начнут лезть баги.
← →
megavoid © (2012-01-22 10:29) [26][0] Можно так, убираем все тэги, при этом то, что за неправильной кавычкой отбрасываем, предварительно помечаем a href, потом возвращаем его на место
function RemoveTags(const s: string): string;
var
i: Integer;
InTag: Boolean;
begin
Result := "";
InTag := False;
for i := 1 to Length(s) do begin
if s[i] = "<" then inTag := True
else if s[i] = ">" then inTag := False
else if not InTag then Result := Result + s[i];
end;
end;
S := "код хтмл";
S := AnsiReplaceStr(S, "<a href=", "$$$$$");
S := AnsiReplaceStr(S, "</a>", "#####");
S := ReplaceTags;
S := AnsiReplaceStr(S, "$$$$$", "<a href=");
S := AnsiReplaceStr(S, "#####", "</a>");
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2012.05.27;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.005 c