:: Обсуждаем проекты
Разбор файлов - как вытащить нужную информацию.
maple4

Сообщений: 210
Откуда: Москва
Дата регистрации: 26.10.2007
В общем, стоит (скорее, стояла...) такая задача:
Из текстового файла (сформированного по какому-то правилу) нужно вытащить НУЖНУЮ информации.
Если известны начальная и конечная позиции блока информации, тогда все очень просто.
Ну а если эти позиции меняются? К чему тогда можно "привязаться"?
Если текстовый файл - страница html, задача значительно упрощается. Якорями (местами "привязки") могут являться характерные комбинации тэгов, особенно если они используют классы или имена.

Как пример - главные новости на mail.ru содержатся между якорями <div class="news"> и </div>

А вот на lenta.ru информация находится между
<TABLE class=peredovica cellSpacing=0 cellPadding=0 width=100% border=0>
и
</TABLE>
Но тут, что бы правильно все вытащить, нужно учитывать парность <TABLE... и </TABLE>, ведь если в содержимом между якорями будет добавлена хотя бы еще одна таблица, результат будет неверным.

Первый вариант - использовать объект IE, и вытаскивать то, что надо, последовательно перебирая тэг за тэгом.
Вариант второй - IE не использовать.

Если присмотреться, блок на lenta.ru заканчивается </TABLE> и далее идет <DIV class=hrg><SPACER type=block></SPACER></DIV>
Так вот, что-бы найти нужный </TABLE> можно найти сначала <DIV class=hrg><SPACER... а потом, уже первый от данной комбинации слева - тот самый тэг </TABLE>.

А вот если таких новостных блоков несколько? Как быть в данном случае, если требуется вытащить их все?

Предлагаю такую схему:
1. Создается некий объект (HC).
2. Ему присваиваются начальный и конечный якоря.
3. Объект по якорям находит начальную и конечную позиции в файле.
4. Если они найдены - вырезается из файла нужный кусок информации, и, далее к шагу 3, но уже к поиску следующих по счету якорей. Если якоря не найдены - выход.



Один нюанс, который касается lenta.ru
Последний блок не заканчивается <DIV class=hrg><SPACER...
Как тогда понять ГДЕ конец блока?
Для этого можно привязаться к другой последовательности символов - <TABLE class=podval> и уже от нее найти первую слева комбинацию символов <br>, которая и является якорем конца блока.

...
Далее, вся информация используется в своих интересах (от вывода на начальную страницу браузера blank ... до незаконного использования в контенте сайта ).

Что бы не быть голословным - пример использования ниже.
А еще чуть ниже - пример альтернативной работы с объектом с помощью скрипта.

И класс в архиве.
-------------------------------------------------------------------------------------------
SET PROCEDURE TO hc.prg ADDITIVE
local tst,tkt
&& перебор новостей, и формирование своей таблицы из них (блоки располагаются в отдельной колонке) + самый первый блок внизу таблицы
tst=CREATEOBJECT("hc")
tst.hc_text([<table border=1><tr>]) && вставка таблицы и строки
IF tst.hc_loadresource("http://www.mail.ru"+"?id="+SYS(2015)) && загрузка с ресурса
WAIT WINDOW "Load ok (1)" TIMEOUT 1
ELSE
WAIT WINDOW "Load ERROR (1)" TIMEOUT 1
RETURN
ENDIF
DO WHILE tst.hc_start_open() ; && начальный якорь
AND tst.hc_tag([<div class="news">],"IN=TRUE") ; && определение комбинации <div class="news"> для якоря
AND tst.hc_start_close() && конец описания якоря и определение позиции "откуда" (START)
&& цикл работает только если последовательность <div class="news"> найдена
tst.hc_end_open()&& конечный якорь
tst.hc_tag([</div>],"IN=TRUE") && определение комбинации </div> для якоря
tst.hc_end_close() && конец описания якоря и определение позиции "досюда" (END)
tst.hc_text([<td align=left valign=top><font size=-1>]) && вставка своего текста в результат - колонки и форматирования текста
tst.hc_insert() && вставка в результат вырезанного от START до END текста
tst.hc_text([</font></td>]) && вставка своего текста - закрытия форматирования текста и колонки
ENDDO
tst.hc_text([</tr></table>]) && вставка своего текста - закрытие строки и таблицы
tst.hc_pointer("SET=0") && перемещение указателя на начало для поиска ТОЛЬКО первого блока <div class="news">
tst.hc_text(CHR(13)+[<hr>]+CHR(13)+CHR(13)+CHR(13)+CHR(13)) && вставка своего текста
tst.hc_start_open()
tst.hc_tag([<div class="news">],"IN=FALSE") && IN=FALSE - текст <div class="news"> в результат не войдет
tst.hc_start_close()
tst.hc_end_open()
tst.hc_tag([</div>],"IN=FALSE") && IN=FALSE - сам якорь </div> в результат не войдет
tst.hc_end_close()
tst.hc_text([<font size=-1>])
tst.hc_insert()
tst.hc_text([</font>])
&& перебор блоков, когда конечный якорь может быть различным и составным
tkt=CREATEOBJECT("hc")
&& создание второго объекта
IF tkt.hc_loadresource("http://www.lenta.ru"+"?id="+SYS(2015)) && с ресурса
WAIT WINDOW "Load ok (2)" TIMEOUT 1
ELSE
WAIT WINDOW "Load ERROR (2)" TIMEOUT 1
RETURN
ENDIF
DO WHILE tkt.hc_start_open();
AND tkt.hc_tag([<TABLE class=peredovica cellSpacing=0 cellPadding=0 width=100% border=0>],"IN=TRUE");
AND tkt.hc_start_close()
&& поиск комбинации <TABLE class=peredovica cellSpacing=0 cellPadding=0 width=100% border=0> для начального якоря
IF NOT (tkt.hc_end_open() ;
AND tkt.hc_tag([<DIV class=hrg><SPACER type=block></SPACER></DIV>],"IN=FALSE") ; && сам якорь - <DIV class=hrg>... - в результат не входит, IN=FALSE
AND tkt.hc_tag([</TABLE>],"IN=TRUE POSITION=-1") ; && найти первую слева (POSITION=-1) комбинацию </TABLE> от <DIV class=....; якорь в результат ВХОДИТ, IN=TRUE
AND tkt.hc_end_close())
&& поиск комбинации </TABLE><DIV class=hrg><SPACER type=block></SPACER></DIV> для конечного якоря
&& если нет такой комбинации (или если это последний блок), то
IF NOT (tkt.hc_end_open() ;
AND tkt.hc_tag([<TABLE class=podval>],"IN=FALSE") ; && якорь в результат не входит, IN=FALSE
AND tkt.hc_tag([<br>],"IN=FALSE POSITION=-1") ; && найти первую слева (POSITION=-1) комбинацию <br> от <TABLE class=podval>; якорь в результат не входит, IN=FALSE
AND tkt.hc_end_close())
&& поиск комбинации <br><TABLE class=podval> для конечного якоря
&& если такой комбинации не найдено - выход из цикла
EXIT
ENDIF
ENDIF
tkt.hc_insert()
ENDDO
&& замена всех относительных ссылок на абсолютные (самый простой способ, но не самый правильный)
tkt.hcv_vihod=STRTRAN(tkt.hcv_vihod,"href=/","href=http://www.lenta.ru/",-1,-1,1)
tkt.hcv_vihod=STRTRAN(tkt.hcv_vihod,[href="/],[href="http://www.lenta.ru/],-1,-1,1)
STRTOFILE(tst.hcv_vihod+"<br><br><hr>"+tkt.hcv_vihod,"vihod.html") && формирование конечного файла
RETURN
-------------------------------------------------------------------------------------------
Функции объекта:
hc_loadresource (resource) - загрузка текста из файла ресурса . Если ресурс начинается с http:// - берется с Интернет, иначе - локально. Текст загружается в hcv_vhod

hc_start_open() - открытие описание начального якоря
hc_start_close() - закрытие описание начального якоря и поиск его в содержимом (при неудаче возвращает .f.), запись позиции в hcv_nacalo
hc_end_open() - открытие описания конечного якоря
hc_end_close() - закрытие описания конечного якоря, поиск его в содержимом (при неудаче возвращает .f.), запись позиции в hcv_konec
hc_text(TEXT) - вставка в результат (hcv_vihod) произвольного текста TEXT
hc_insert(parameters) - запись в hcv_part содержимого между hcv_nacalo и hcv_konec, и, в зависимости от параметра, запись в результат hcv_vihod
hc_pointer(parameters) - перемещение указателя (hcv_ukaz) в нужную позицию
hc_tag(TEXT,parameters) - описание якоря. TEXT - символьная комбинация


Свойства объекта:
hcv_ukaz - позиция указателя. "Перемещается" при поиске якорей.
hcv_nacalo - позиция начального якоря
hcv_konec - позиция конечного якоря
hcv_vihod - результат
hcv_part - последний найденный блок
hcv_vhod - текст, обрабатываемый объектом
hcv_resource - с какого ресурса получен текст


Для некоторых методов можно задавать параметры:
hc_tag
POSITION=-NNNNN|NNNN : где искать комбинацию символов, слева от указателя (при -) или справа, и какой по счету - NNNN. Если не указан параметр, действие аналогично как при POSITION=1
IN=FALSE|TRUE : не входит или входит якорь в результат (касается только последнего, если он составной)
CASE=FALSE|TRUE : поиск не зависит или зависит от регистра

hc_insert
NOINSERT=FALSE|TRUE : НЕ вставлять (TRUE) или вставлять вырезанный блок текста в результат (в hcv_part - находится вырезанный кусок, его можно обработать и решить, что с ним делать дальше)

hc_pointer
SET=NNNN : перемещение указателя на нужную позицию, например при SET=0 казатель переместится на начало обрабатываемого текста.


-------------------------------------------------------------------------------------------


А вот пример того же самого, но сделанного по другому (типа, "смотрите, как еще можно ") для сайта mail.ru
Предварительно пишется некий файл разбора (не на FoxPro!), называется mailru.txt (кладется в каталог запуска, хотя можно задать и ресурс в Интернет-е, начиная с http:// ).

*************************************************************
**** mailru.txt - файл разбора
[[[[TEXT]]]]<table border=1><tr>[[[[/TEXT]]]] - код таблицы со строкой
[[[[ADDRESS ADDRESS=T1]]]] - адрес (согласен, не структурное программирование...)
задание начального якоря, если якорь не будет найден - переход на адрес T2
[[[[START ELSE=T2]]]]
[[[[TAG IN=TRUE]]]]<div class="news">[[[[/TAG]]]]
[[[[/START]]]]
задание конечного якоря
[[[[END]]]]
[[[[TAG IN=TRUE]]]]</div>[[[[/TAG]]]]
[[[[/END]]]]
вставка колонки
[[[[TEXT]]]]<td align=left valign=top><font size=-1>[[[[/TEXT]]]]
... и данных
[[[[INSERT]]]]
вставка закрытия колонки
[[[[TEXT]]]]</font></td>[[[[/TEXT]]]]
переход на адрес T1
[[[[GOTO GOTO=T1]]]]
[[[[ADDRESS ADDRESS=T2]]]] - адрес T2
[[[[TEXT]]]]</tr></table>[[[[/TEXT]]]] - вставка кода закрытия таблицы
[[[[POINTER SET=0]]]] - переместить указатель на начало
вставка текста
[[[[TEXT]]]]
<hr>
[[[[/TEXT]]]]
далее - поиск и вставка только САМОГО первого блока новостей
[[[[START]]]]
[[[[TAG IN=FALSE]]]]<div class="news">[[[[/TAG]]]]
[[[[/START]]]]
[[[[END]]]]
[[[[TAG IN=FALSE]]]]</div>[[[[/TAG]]]]
[[[[/END]]]]
[[[[TEXT]]]]<font size=-1>[[[[/TEXT]]]]
[[[[INSERT]]]]
[[[[TEXT]]]]</font>[[[[/TEXT]]]]
*****
*************************************************************



Далее, уже на FoxPro, создается объект, который и делает всю работу сам:

*************************************************************
SET PROCEDURE TO hc.prg ADDITIVE
local tst
tst=CREATEOBJECT("hc")
tst.run_script("http://www.mail.ru"+"?id="+SYS(2015),"mailru.txt")
STRTOFILE(tst.HCV_VIHOD,"vihod.html")
*************************************************************


В общем, два варианта работы с объектом:
1. На чистом FoxPro - в этом случае у Вас полный контроль над объектом
2. Варант со скриптом, который позволяет сделать многое, не особо вникая в Fox.


самый новый архив с объектом и примерами работы находится здесь (прямая ссылка на загрузку, 8кб):

www.maple4.ru

-------------------------------------------------------------------------------------------
P.S.
Может, кто делает по другому? Например, с помощью регулярных выражений.

P.P.S.
Про RSS знаю. И "разбирать" похожим образом можно не только html-файлы.

P.P.P.S.
Все пока на этапе тестирования. Кроме того, хотелось бы для себя понять - "а зачем?"
Есть возможность развиваться дальше.
Например, считывание блока информации размером сколько-то символов, если структура данных статична.
Ratings: 0 negative/0 positive
Re: Разбор файлов - как вытащить нужную информацию.
JS
Автор

Сообщений: 12264
Откуда: Эстония
Дата регистрации: 04.09.2000
maple4
А вот на lenta.ru информация находится между
<TABLE class=peredovica cellSpacing=0 cellPadding=0 width=100% border=0>
и
</TABLE>

Как все было бы проще, если бы создатели сайтов и их страниц использовали
атрибут id. В таком случае, большинство задач бы по разбору информации
упрощалась бы многократно, так как есть замечательный метод getElementById.


------------------
Knowledge is better than ignorance!
Website: juri.foxhelp.eu
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 3 (Гостей: 3)

© 2000-2024 Fox Club 
Яндекс.Метрика