Автор Тема: HTML в TXT  (Прочитано 4504 раз)

Оффлайн Mozgorep

  • Старшеклассник
  • ***
  • Сообщений: 128
  • Репутация: 2
HTML в TXT
« : 10 Июль 2006, 13:44:55 »
Вобщем так, есть такая задача: нужно из html выдрать весь "полезный текст", т.е. тот, который виден в окне браузера. Сначала я делал так: включал в выходной файл все, что находится между символами ">" и "<". Но в ходе тестирования оказалось что эти симолы могут быть и в "полезном" тексте, например:

<font color="#000099">To uninstall a earlier version, run the Corel Uninstall program from <b>Start > Programs > CorelDRAW > Setup and notes</b> (or <b>Start > Settings > Control panel > Add/remove programs</b> and select <b>Corel Applications</b> from the Install/Uninstall tab).</font>

Вот... какие у вас есть идеи по этому поводу?

Оффлайн GogA

  • Автор
  • Студент
  • *****
  • Сообщений: 564
  • Репутация: 22
  • root :)
    • gogolev.net
HTML в TXT
« Ответ #1 : 10 Июль 2006, 13:58:00 »
Конвертация HTML в текст
Код: (php) [Выделить]
// $document должен содержать HTML-документ.
// Здесь будут удалены тэги HTML, разделы javascript
// и пустое пространство. Также некоторые обычные элементы
// HTML конвертируются в их текстовые эквиваленты.

$search = array ("'<script[^>]*?>.*?</script>'si",  // Вырезается javascript
                 "'<[\/\!]*?[^<>]*?>'si",           // Вырезаются html-тэги
                 "'([\r\n])[\s]+'",                 // Вырезается пустое пространство
                 "'&(quot|#34);'i",                 // Замещаются html-элементы
                 "'&(amp|#38);'i",
                 "'&(lt|#60);'i",
                 "'&(gt|#62);'i",
                 "'&(nbsp|#160);'i",
                 "'&(iexcl|#161);'i",
                 "'&(cent|#162);'i",
                 "'&(pound|#163);'i",
                 "'&(copy|#169);'i",
                 "'&#(\d+);'e");                    // вычисляется как php

$replace = array ("",
                  "",
                  "\\1",
                  "\"",
                  "&",
                  "<",
                  ">",
                  " ",
                  chr(161),
                  chr(162),
                  chr(163),
                  chr(169),
                  "chr(\\1)");

$text = preg_replace ($search, $replace, $document);

Оффлайн Nik

  • Кандидат IT-наук
  • ********
  • Сообщений: 3316
  • Репутация: 726
  • Мастер-арфист
    • "Новый Мегабайт"
HTML в TXT
« Ответ #2 : 10 Июль 2006, 14:18:38 »
Когда-то я писал функцию для удаления тегов на Delphi.

Код: (delphi) [Выделить]
function Dele teTags(str: string): string;
var
 LenStr: integer;
 tempSimbol: string;
 j, k: integer;
 chTr: boolean;
 temp1, temp2: string;
begin
   result:='';
   LenStr:=Length(str);
   MainEdit.OperProgress.Max:=LenStr;
   // Начало обработки
   j:=1;
   while j<=LenStr do
    begin
     chTr:=false;
     // Проверка символа на наличие замены в таблице
     for k:=1 to NumOfTags do
      begin
       tempSimbol:=Copy(str, j, Length(TagsList[k]));
       if tempSimbol=TagsList[k]
        then
         begin
          temp1:=Copy(str, 1, j-1);  // строка до тега
          temp2:=Copy(str, (j+1+Length(tempSimbol)), LenStr-Length(temp1));
          result:=temp1+temp2;
          j:=j+1;
          chTr:=true;
          exit;
         end;
       end;
     // Если замена не найдена, то оставляем исходный символ
     if (chTr=false) then
      begin
       result:=result+tempSimbol;
       j:=j+1;
       exit;
      end;
     MainEdit.OperProgress.Position:=j;
    end;
end;


// Чтение тегов из файла
procedure ReadTable(TableFile: string);
var
 i: integer;
 temp: string;
 TagsFile: textFile;
begin
 // Чтение первой таблицы
 AssignFile(TagsFile, TableFile);
 Reset(TagsFile);
 readln(TagsFile, temp);
 NumOfTags:=StrToInt(temp);
 for i:=0 to NumOfTags do readln(TagsFile, TagsList[i]);
 CloseFile(TagsFile);
end;


А вот образец файла с тегами:
Цитировать
108
A
B
DD
I
H1
H2
H3
H4
H5
H6
DL
P
KBD
Q
BIG
EM
HEAD
S
BR
DEL
LI
U
ABBR
DFN
DT
TD
AREA
HR
BASE
CODE
OL
TH
EMBED
IMG
COL
MAP
DIR
LABEL
UL
DIV
CITE
THEAD
TR
META
PRE
TABLE
TT
var
INS
SUB
FRAME
WBR
BODY
LINK
LEGend
BLINK
NOBR
PARAM
SAMP
SPAN
FORM
IFRAME
HTML
MENU
XMP
FONT
object
SUP
SMALL
NOEMBED
LAYER
SPACER
SELECT
CENTER
TBODY
TITLE
KEYGEN
ADDRESS
APPLET
ILAYER
NEXTID
TFOOT
CAPTION
FIELDSET
INPUT
MARQUEE
STYLE
BASEFONT
BGSOUND
STRIKE
COMMENT
ISINDEX
SCRIPT
SERVER
FRAMESET
ACRONYM
OPTION
LISTING
NOLAYER
NOFRAMES
BUTTON
STRONG
TEXTAREA
MULTICOL
COLGROUP
NOSCRIPT
BLOCKQUOTE
PLAINTEXT

Конечно, эта функция далеко не идеальна, но с основной задачей справляется :)   Да и писал-то я ее почти пять лет назад скорее ради интереса... Но вдруг пригодится :)
И время всякому делу под небесами...

Оффлайн GogA

  • Автор
  • Студент
  • *****
  • Сообщений: 564
  • Репутация: 22
  • root :)
    • gogolev.net
HTML в TXT
« Ответ #3 : 10 Июль 2006, 17:12:47 »
Nik, а у тебя прога с такой строчкой справится:
Цитировать
<a href="qwe.ru" style="color: #111111;">qwe.ru</a>
?

Оффлайн Anton Konkin

  • Абитуриент
  • ****
  • Сообщений: 302
  • Репутация: 7
    • Браузер Opera и его русификация
HTML в TXT
« Ответ #4 : 10 Июль 2006, 18:11:57 »
Цитировать
Вобщем так, есть такая задача: нужно из html выдрать весь "полезный текст", т.е. тот, который виден в окне браузера. Сначала я делал так: включал в выходной файл все, что находится между символами ">" и "<". Но в ходе тестирования оказалось что эти симолы могут быть и в "полезном" тексте, например:
Зачем мудрить, ведь Опера может прекрасно сохранять любую HTML страницу в вормате TXT ;)


Оффлайн Mozgorep

  • Старшеклассник
  • ***
  • Сообщений: 128
  • Репутация: 2
HTML в TXT
« Ответ #5 : 10 Июль 2006, 19:06:28 »
сорри, забыл добавить, я пишу на Delphi и на С++. Так что, GogA, извини, PHP не подходит.

Nik, спасибо за исходники. Правда, еще не совсем понял, как это работает :), например, как будет обрабатываться текст <font color="#000099">? Слова font и  color удалятся, а "#000099"> как я понял останется, в этом заключается неидеальность?

Цитировать
Зачем мудрить, ведь Опера может прекрасно сохранять любую HTML страницу в вормате TXT
нужна именно своя процедура, которая кучу html преобразует в txt.

А как это делает опера? Может у нее позаимствовать?  :)

Оффлайн Anton Konkin

  • Абитуриент
  • ****
  • Сообщений: 302
  • Репутация: 7
    • Браузер Opera и его русификация
HTML в TXT
« Ответ #6 : 10 Июль 2006, 19:25:07 »
Цитировать
А как это делает опера? Может у нее позаимствовать?


Лучше задать этот вопрос на форуме сайта operafan.net


Оффлайн Nik

  • Кандидат IT-наук
  • ********
  • Сообщений: 3316
  • Репутация: 726
  • Мастер-арфист
    • "Новый Мегабайт"
HTML в TXT
« Ответ #7 : 10 Июль 2006, 19:29:24 »
Я, если честно, уже не помню, как моя программа справлялась с такими записями :)  Вечером гляну...
И время всякому делу под небесами...

Оффлайн Mozgorep

  • Старшеклассник
  • ***
  • Сообщений: 128
  • Репутация: 2
HTML в TXT
« Ответ #8 : 11 Июль 2006, 11:27:19 »
Nik, не понимаю как работает эта функция  ::)
Например, зачем выходить из функции после первого найденного тега?
if tempSimbol=TagsList[k]
        then
         begin
          ...
          exit;
         end;
       end;

в который уже раз заглянул в поиск и ... нашел кое-что дельное:

Использование функциональности IE или заметки о WebBrowser
Визуальный HTML редактор своими руками
Как получить текст HTML Документа из TWebBrowser без   тегов
Подсветить HTML   теги   в RichEdit

Щас буду во всем этом разбираться...

Оффлайн Nik

  • Кандидат IT-наук
  • ********
  • Сообщений: 3316
  • Репутация: 726
  • Мастер-арфист
    • "Новый Мегабайт"
HTML в TXT
« Ответ #9 : 11 Июль 2006, 11:56:44 »
Цитировать
Например, зачем выходить из функции после первого найденного тега?
Там все хитро - функция сверяет каждый найденный фрагмент (похожий на тег) с каждым элементом списка. Если совпадение есть, цикл прерывается... Я же говорил - функция очень не оптимальна :)


Цитировать
Как получить текст HTML Документа из TWebBrowser без   тегов
Сдается мне, что в твоем случае это будет самый простой вариант. На Delphi пишется в лет :)
И время всякому делу под небесами...

Оффлайн YaricZ

  • Автор
  • Дипломированный IT-шник
  • *****
  • Сообщений: 1380
  • Репутация: 150
  • живу как умею
    • живое отражение живой жизни
HTML в TXT
« Ответ #10 : 12 Июль 2006, 18:12:23 »
Инсайт!

Можешь написать самопальный браузер, загрузить в него страничку (компонент MI Control), выполнить команду выделения текста и скопировать её в буфер обмена.
Живи

Оффлайн Mozgorep

  • Старшеклассник
  • ***
  • Сообщений: 128
  • Репутация: 2
HTML в TXT
« Ответ #11 : 12 Июль 2006, 18:46:15 »
Цитировать
компонент MI Control
что-то я не нашел такого компонента...
Цитировать
выполнить команду выделения текста и скопировать её в буфер обмена
если не сложно, напиши код  ::) не работал я с буфером

Оффлайн Nik

  • Кандидат IT-наук
  • ********
  • Сообщений: 3316
  • Репутация: 726
  • Мастер-арфист
    • "Новый Мегабайт"
HTML в TXT
« Ответ #12 : 12 Июль 2006, 19:24:12 »
Я нашел подходящий пример. Итак, кидаешь на форму один экземпляр TWebBrowser, и используешь вот эту процедуру:

uses mshtml, activex;

Код: (delphi) [Выделить]
procedure GetHtmlCode(WebBrowser: TWebBrowser; FileName: string);
var
 htmlDoc: IHtmlDocument2;
 PersistFile: IPersistFile;
begin
 htmlDoc := WebBrowser.document as IHtmlDocument2;
 PersistFile := HTMLDoc as IPersistFile;
 PersistFile.save(StringToOleStr(FileName), true);
end;

И время всякому делу под небесами...

Оффлайн Mozgorep

  • Старшеклассник
  • ***
  • Сообщений: 128
  • Репутация: 2
HTML в TXT
« Ответ #13 : 13 Июль 2006, 09:13:18 »
Я пробовал использовать этот код, проблема в том, что страничка должна быть уже загружена в WebBrowser. Если написать этот код в событии NavigateComplete2, то при открытии больших файлов сохраняется не весь текст. А если подождать немного и потом выполнить этот код, то все нормально.
Попробовал загружать файл сразу в IHtmlDocument2 как написано тут
var s: string;
    F: TFileStream;
begin
  f:=TFileStream.Create('d:\pumpumpum.html', fmOpenRead);
  try
  SetLength(s, f.size);
  f.Read(PChar(s)^, Length(s));//помещаем html в строку
  Doc:=CoHTMLDocument.Create;
  OleVariant(Doc).write(s);//пишем эту строку в документ
//Можно загружать через VarArray и переменную
  //IHtmlDocument2, я здесь делаю так, через строку
  //и OleVariant
  Doc.close;
  finally
    F.free;
  end
далее пишу PersistFile := Doc as IPersistFile;, но вместо текста в выходной файл пишутся крякозяблики. Как загрузить через VarArray и переменную IHtmlDocument2?

Оффлайн Mozgorep

  • Старшеклассник
  • ***
  • Сообщений: 128
  • Репутация: 2
HTML в TXT
« Ответ #14 : 14 Июль 2006, 15:54:15 »
Цитировать
в выходной файл пишутся крякозяблики
Это Unicode....

Оффлайн Alex_K

  • Ученик
  • **
  • Сообщений: 68
  • Репутация: 26
    • www.koscheev.ru
HTML в TXT
« Ответ #15 : 15 Июль 2006, 23:42:33 »
Цитировать
Вобщем так, есть такая задача: нужно из html выдрать весь "полезный текст", т.е. тот, который виден в окне браузера. Сначала я делал так: включал в выходной файл все, что находится между символами ">" и "<". Но в ходе тестирования оказалось что эти симолы могут быть и в "полезном" тексте, например:

<font color="#000099">To uninstall a earlier version, run the Corel Uninstall program from <b>Start > Programs > CorelDRAW > Setup and notes</b> (or <b>Start > Settings > Control panel > Add/remove programs</b> and select <b>Corel Applications</b> from the Install/Uninstall tab).</font>

Вот... какие у вас есть идеи по этому поводу?

Вообще-то знаки [<>] в "полезном" тексте недопустимы, поэтому вариант вырезания тегов с помощью простеньких регулярных выражений сработает.

Оффлайн Mozgorep

  • Старшеклассник
  • ***
  • Сообщений: 128
  • Репутация: 2
HTML в TXT
« Ответ #16 : 16 Июль 2006, 09:41:58 »
Цитировать
Вообще-то знаки [<>] в "полезном" тексте недопустимы
Я тоже сначала так думал, но потом оказалось, что не все так просто. Приведенный фрагмент на экране выглядит так:
To uninstall a earlier version, run the Corel Uninstall program from Start > Programs > CorelDRAW > Setup and notes (or Start > Settings > Control panel > Add/remove programs and select Corel Applications from the Install/Uninstall tab)
Попробуйте сами, если не верите :). В ходе экспериментов выяснилось, что текст между знаками <  > браузеры считают тегом, если он написан сразу после знака <, т.е. <b> - это тег, а < b> - уже нет. Так что это уже не проблема :)
Зато есть вопрос. Оказывается есть такие теги, текст между которыми не является "полезным", например, <STYLE>  </STYLE>. Есть ли еще подобные теги?

Оффлайн Alex_K

  • Ученик
  • **
  • Сообщений: 68
  • Репутация: 26
    • www.koscheev.ru
HTML в TXT
« Ответ #17 : 18 Июль 2006, 23:35:05 »
Цитировать
Я тоже сначала так думал, но потом оказалось, что не все так просто. Приведенный фрагмент на экране выглядит так:
To uninstall a earlier version, run the Corel Uninstall program from Start > Programs > CorelDRAW > Setup and notes (or Start > Settings > Control panel > Add/remove programs and select Corel Applications from the Install/Uninstall tab)
Попробуйте сами, если не верите . В ходе экспериментов выяснилось, что текст между знаками <  > браузеры считают тегом, если он написан сразу после знака <, т.е. <b> - это тег, а < b> - уже нет. Так что это уже не проблема
Зато есть вопрос. Оказывается есть такие теги, текст между которыми не является "полезным", например, <STYLE>  </STYLE>. Есть ли еще подобные теги?

Я  к тому, что то, что отображается в браузере знаками больше или меньше должно быть безопасной HTML-последовательностью, т.е. &lt; и &gt;
Как отображает браузер теги с установленным пробелом внутри после знака меньше - это его личное дело (и его разработчиков конечно, же), он в праве вообще не показывать всё, что заключено между знаками <>.

Тег STYLE допустим согласно спецификации толко внутри HEAD. Соответственно "полезный" текст будет находится ТОЛЬКО внутри тега BODY. Наличие внутри BODY тегов STYLE и правильная их инетрпертация бразуером, еще не гвоорит о том, что HTML правильный.

Оффлайн GogA

  • Автор
  • Студент
  • *****
  • Сообщений: 564
  • Репутация: 22
  • root :)
    • gogolev.net
HTML в TXT
« Ответ #18 : 19 Июль 2006, 02:10:52 »
<img src="px.gif" alt="parent > child" style="width: 1px; height.gif" />

:D

вообще код не верный :) так как w3c рекомендует все < > внутри тегов заменять на &lt; и &gt

но такие примеры встречаются :)


кстати, по результатам работы скрипта из второго сообщения
после:
Цитировать
<font color="#000099">To uninstall a earlier version, run the Corel Uninstall program from <b>Start > Programs > CorelDRAW > Setup and notes</b> (or <b>Start > Settings > Control panel > Add/remove programs</b> and select <b>Corel Applications</b> from the Install/Uninstall tab).</font>

выдаёт:
Цитировать
To uninstall a earlier version, run the Corel Uninstall program from Start > Programs > CorelDRAW > Setup and notes (or Start > Settings > Control panel > Add/remove programs and select Corel Applications from the Install/Uninstall tab).

хотя для <img src="px.gif" alt="parent > child" style="width: 1px; height.gif" /> видать нужны более серьёзные регулярные выражения.. да и не факт что регулярные справятся :)

Оффлайн GogA

  • Автор
  • Студент
  • *****
  • Сообщений: 564
  • Репутация: 22
  • root :)
    • gogolev.net
Re: HTML в TXT
« Ответ #19 : 19 Июль 2006, 02:24:35 »
2 Mozgorep:
вот ещё парочка :)
<script *> </script>
<object *> </object>

не забудь про всякие комментарии <!-- -->... вроде это не единственный

Оффлайн Mozgorep

  • Старшеклассник
  • ***
  • Сообщений: 128
  • Репутация: 2
HTML в TXT
« Ответ #20 : 22 Июль 2006, 17:06:42 »
привожу 2 варианта решения, вдруг кому понадобится :)
Вариант первый, с использованием трудов ребят из MS
function Html2Txt(S:PChar; var len:integer):boolean;
var
  Doc: DispHTMLDocument;
  str:string;
begin

result:=true;
try
      SetString(str,S,len);
      Doc:=CoHTMLDocument.Create;
      OleVariant(Doc).write(str);
      str:=(Doc as IHtmlDocument2).body.innerText;
      len:=length(str);
      StrPCopy(S,str);
except
    result:=false;
end;

end;
Вариант второй, без использования трудов ребят из MS :)
function Clean(S: PChar; var len:integer): boolean;
var
  tag, tagI, ExecTag: boolean;
  i,t,TagBegin,dlina: integer;
  temp:string[6];
  ch:Byte;
begin
  result:=true;
try
  temp:='ABCDEF';
  dlina:=-1; TagBegin:=0;
  tag:=false;
  tagI:=false;
  ExecTag:=false;
  dec(len);
  for i:=0 to len do begin
    case S[i] of
      '<':  case S[i+1] of
                'A'..'Z',
                'a'..'z',
                '!', '%',
                '/', '?': begin
                            tag:=true;
                            TagBegin:=i;
                            if S[i+1]='/' then inc(TagBegin);
                            continue;
                          end;
              end;
      '&':  if ((not tag)and (not ExecTag)) then
              case S[i+1] of
                'A'..'Z',
                'a'..'z',
                '0'..'9',
                '#': begin
                       tagI:=true;
                       continue;
                     end;
              end;
      ';',' ':  if ((not tag) and tagI and (not ExecTag)) then
                  begin
                    tagI:=false;
                    continue;
                  end;
      '>':  begin
              if tag then begin
                tag:=false;

                for t:=1 to 6 do
                  begin
                    temp[t]:=S[TagBegin+t];
                    ch:=ord(temp[t]);
                    if ((ch>$40)and(ch<$61)) then temp[t]:=chr(ch+$20);
                  end;
               
                if ( (Pos('style',temp)=1) or
                     (Pos('script',temp)=1) or
                     (Pos('object',temp)=1) ) then
                  ExecTag:=not ExecTag;
                 
                continue;
              end;
            end;
    end;

    if ((not tag) and (not tagI) and (not ExecTag)) then
      begin
        inc(dlina);
        S[dlina]:=S[i];
      end;

  end;
  len:=dlina+1;
  S[len]:=#0;
except
  result:=false;
end;

end;