LINUX.ORG.RU

Кто интересуется выдиранием данных из HTML. Предлагаю посмотреть на мою библиотеку «tagstractor».


0

2

http://ymap.org/prog/tt/

Это не попытка конкуренции с существующими вещами, типа XPath (который для XML, а реальный HTML не всегда XML), Web::Scraper и т.п., просто ещё один способ.

Всё ещё сырое, включая документацию.

★☆

Последнее исправление: kiverattes (всего исправлений: 1)

Где ж ты был неделю назад...
Я тут свой огород костылей на awk соорудил, чтобы распарсить единственную страницу. Возникнет еще потребность чего-нибудь раздеребанить - взгляну как-нить. Сайт добавил в закладки.

malices_gossips ★★★
()

Заход номер 2? ;)

Это не попытка конкуренции с существующими вещами,

типа XPath (который для XML, а реальный HTML не всегда XML)



XPath работает на DOM, любая вменяемая библиотека для работы с XML обычно имеет и невалидирующий HTML-парсер, а полученное DOM-дерево можно спокойно обрабатывать с помощью XPath. И в большинстве случае это и будет самый простой выдирания информации из HTML.

При желании может посоревноваться в том, как будет проще.

archimag ★★★
()

Это плохо что я RegExp (Qt, Boost, C++0x) пользуюсь - да?

Меня колесовать нужно?

Ещё циклы с итераторами и лямбдами при всём этом иногда использую. Конечно ещё не стояло задач по выдёргиванию, например данных из ячеек таблицы, которые лежат на пересечении чётных столбцов и нечётных строк. Но стояла задача выбрать div с class, начинающимся на определённую комбинацию символов, а потом из этого div нужно было вытащить из вложенной таблички ячейки второго столбца, с отбрасыванием пробелов в начале и конце, а также в первой ячейке нужно было убрать форматирование жирным.

Результат: Цикл с применением одного регулярного выражения, и применения второго регулярного выражения к результату первого.

Если у Вас это можно сделать одним махом(шаблоном), то есть смысл использовать Вашу библиотеку.

m4n71k0r
()

Название tagsvelosiped уже занято, что ли?

anonymous
()
Ответ на: комментарий от m4n71k0r

>HTML

Это плохо что я RegExp … пользуюсь


Да.

Deleted
()
Ответ на: комментарий от m4n71k0r

Если у Вас это можно сделать одним махом(шаблоном), то есть смысл использовать Вашу библиотеку.

Наверное можно, проблема только в сравнении начала строки с опр. подстрокой. Простой find (haystack, needle) есть, но у вас привязка к началу...

Пример HTML-кода:

<b>hahaha</b>
<div class="sub117">Bububu</div>
<div class="mtmt999">
<table>
<tr><td>11<td>12<td>13
<tr><td>21<td>22<td>23
<tr><td>31<td>32<td>33
<tr><td>41<td>42<td>43
</table>
</div>

Мой шаблон под то, что вы хотите, будет примерно таким:

DIV CLASS == "mtmt999" $i=0, table, (tr,td,text,td,text $t[$i]=data, td,text $i=$i+1) +, /table, /div

Или:

DIV find(CLASS,"mtmt") $i=0, table, (tr,td,text,td,text $t[$i]=data, td,text $i=$i+1) +, /table, /div

Вторая колонка таблицы зафигачится в массив $t[].

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

Вот мой код (на Common Lisp) который позволяет рекурсивно загрузить всех стихи автора с сайта www.stihi.ru и разложить их все по файлам в папках (точно как сделано у автора на странице).

(defun load-poem (url dir &key verbose)
  (html:with-parse-html (page url :encoding "cp1251")
    (let* ((index (xpath:find-single-node page "/html/body/index"))
           (title (xpath:find-string index "h1")))
    (when verbose
      (format t "Load ~A (~A)~%" url title))
    (with-open-file (out (make-pathname :directory (pathname-directory dir)
                                        :name title
                                        :type "txt")
                         :direction :output :if-exists :supersede)
      (iter (for br in (xpath:find-list index "div[@class='text']/br"))
            (write-line (string-trim #(#\Newline)
                                     (xtree:text-content (xtree:prev-sibling br)))
                        out))))))
                 
(defun load-all-poems (url target &key verbose (recursive t))
  (ensure-directories-exist target)
  (html:with-parse-html (page url :encoding "cp1251")
    (iter (for node in (xpath:find-list page "//ul/li/a"))
          (load-poem (puri:merge-uris (puri:parse-uri (xtree:attribute-value node "href"))
                                      url)
                     target
                     :verbose verbose))
    (when recursive
      (iter (for node in (xpath:find-list page "//div[@id='bookheader']/a"))
            (let ((title (xtree:text-content node)))
              (when verbose
                (format t "~%Load book ~A~%" title))
              (load-from-stihiru (puri:merge-uris (puri:parse-uri (xtree:attribute-value node "href"))
                                                  url)
                                 (merge-pathnames (make-pathname :directory (list :relative title))
                                                  target)
                                 :recursive nil
                                 :verbose verbose))))))

Здесь информация вынимается тривиальнейшим образом на основе XPath запросов, а как это будет выглядеть у вас?

archimag ★★★
()
Ответ на: комментарий от archimag

А вы покажите страницу (дайте ссылку), с которой происходит выгребание и напишите, что конкретно из неё нужно выдрать.

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

> А вы покажите страницу (дайте ссылку), с которой происходит

выгребание и напишите, что конкретно из неё нужно выдрать.


Например - http://www.stihi.ru/avtor/cotbace. Это страница автора. С неё идут ссылки на стихи, а также на категории (книги), где также есть стихи. Надо скачать все стихи автора (голый текст, без html-разметки).

archimag ★★★
()
Ответ на: комментарий от archimag

HTTP-запросы из tagstractor не делаются, он жрёт только выданную ему HTML-страницу. Выдирание одного стиха со страницы и возложение его в переменную $txt, а названия в $title выглядит так:

index $txt = "", h1, text $title=data, /h1,
div class == "titleauthor", em, a, text, /a, /em, /div,
div class == "text",
( TEXT $txt = $txt+data : BR )+, /div

"(text $txt=$txt+data : BR) +" - означает «встретить много раз (+) либо тег TEXT (просто кусок текста), либо тег BR. При этом у тега TEXT задана операция, которая в переменную $txt постоянно добавляет очередной встреченный кусок текста.

Под каждый тип страницы („стих“, „список стихов“ и др.) будет свой шаблон. Берём шаблон „список стихов“, кидаем ему страницу со списком стихов, получаем массив урлов на стихи. Качаем гору страниц со стихами, скармливаем их шаблону „стих“, получаем с каждой страницы одну переменную $txt со стихом.

Т.е. tagstractor будет работать как какая-нибудь RegExp-библиотека, заточенная под HTML, которую использует какое-то приложение.

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

Так в чём тогда смысл данной системы? Выкачать отдельный стих и вывести на стандартный вывод я могу так:

(html:with-parse-html (page #U"http://www.stihi.ru/2008/06/02/1549" :encoding "cp1251")
  (iter (for node in-xpath-result "/html/body/index/div[@class='text']/br" on page)
        (write-line (string-trim #(#\Newline)
                                 (xtree:text-content (xtree:prev-sibling node))))))

Т.е. я использую совершенно стандартные (XPath) возможности и при этом сохраняю все возможности основного языка (могу дополнительно обрабатывать строки, например) и могу при этом делать HTTP-запросы.

archimag ★★★
()
Ответ на: комментарий от archimag

>Так в чём тогда смысл данной системы?

bicycle //c.o.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.