Drupal → Модуль Parser — парсинг сайтов

17.06.2011

Описание

Модуль Parser предназначен для парсинга любых html страниц в сущности (ноды, термины, юзеры и т.д.). Собственно на этом описание модуля можно закончить =)

Парсинг

Принцип работы парсера похож на работу поисковиков — он загружает одну из страниц сайта, ищет на ней ссылки и начинает ходить по ним в глубь. Встретив страницу, которая попадает под условие "распарсить эту страницу", модуль создает объект сущности и начинает выполнять пользовательский php код, заполняя поля и свойства. Картинки выкачиваются на сервер, создаются отсутствующие термины, значения приводятся к нужному типу.

Использование

Сразу хочу предупредить, что без знаний php работать с модулем будет крайне затруднительно.

Задания парсера находятся по адресу admin/structure/parser_jobs. По умолчанию там есть только одно — Парсинг шаблонов с drupal.org, которое можно использовать как мануал.

Как начать парсить сайт:

  1. Создаём задание admin/structure/parser_jobs/add.
  2. В поле Стартовый URL указываем начальный адрес. С него парсер начнёт работу.
  3. В поле URL тестовой страницы указываем адрес любой страницы, которая в будущем будет распарсена в ноду. HTML код этой страницы будет использован в качестве полигона.
  4. В поле Глубина указываем глубину, до которой парсер будет шагать по найденным ссылкам (простыми словами, глубина — это количество кликов, которые надо сделать относительно страницы указанной в Стартовый URL, чтобы добраться до страницы с контентом).
  5. Заполняем белый и чёрный список адресов.
  6. В поле Код проверки для дальнейшего парсинга страницы пишем код, который должен вернуть TRUE, если текущая страница попадает под условие "распарсить страницу в ноду".
  7. Указываем тип сущности, которая будут создаваться модулем.
  8. Для каждого поля пишем php код, возвращающий значение поля. В коде можно использовать весь функционал библиотеки phpQuery, парсинг с которой превращается в удовольствие :) С помощью кнопок "проверить" смотрим результат работы кода.
  9. Делаем полный бэкап базы и файлов! При неправильной конфигурации модуль может насоздавать много лишних нод.
  10. Начинаем парсинг.

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

Скриншот 1
Скриншот 2
Скриншот 3

Скачать модуль
Пример парсинга сайта drupalsn.ru

Написанное актуально для
Parser 7.x-2.x
Похожие записи

Комментарии

Норм... затестим))) Но это больше модуль для ленивых

Гость
20.06.2011, 16:39

Спасибо за статью.
Нет ли желания переделать и под шестерку тоже? Так то пока еще очень надо.
Спасибо

Гость
22.06.2011, 16:56

Спасибо, распробовал. Самому нравится phpQuery

feeds + xpath | querypath
реалізовує це набагато краще, як на мене + гнучкість з обробкою по ходу і впихуванням куди завгодно

к "feeds + xpath | querypath" как понимаю ещё нужен Feeds Crawler? если да, то под семёрку он не работает

Алексей
25.06.2011, 19:52

Не понимаю как он устанавливается. Пишет в списке модулей "Зависит от Entity (не найден)". Не подскажете в чем может быть причина? Модуль интересно попробывать )

Vikky Shostak
03.09.2011, 21:04

Огромное человеческое спасибо за модуль! :)
На дня два облегчил работу по переносу контента из одного старого проекта в новый ;)

СПА-СИ-БО!

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

к примеру, я оставил на ночь компьютер парсить (потом через час инет оборвался и заново подключился но парсинг уже остановился

тогда может возможно реализовать (паузу старт ) парсинга

К примеру парсит оно 10 000 страниц (интернет оборвался на 3 000 , что бы можно было нажать продолжить и что бы оно дальше парсило ,а не с начала)

реально такое?

У меня такой вопрос,как сделать так что бы парсер не парсил новые статьи,а только обновил существующие.

(первый раз парсилось 3 000 страниц ,потом 10 000 и вышло так (что первые 3000 большинство не обновилось-я создал новые поля и оно туда ничего не загнало из етой старой 3 000 постов)

можно как то решить это?

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

Антон
09.10.2011, 21:19

> парсинг довольно длительная операция и в один запуск крона она никак не уложится

У меня парсится всего 60 страниц. Может быть они уложатся в запуск одного крона? Как это можно проверить?

я не нашёл красивой возможности запустить batch api в кроне, а писать две реализации пока нет желания

а реально прикрутить гугл транслейт к парсеру?

реально, но я этим заниматься не буду

BigForceGun
16.11.2011, 20:57

xandeadx
А почему модуля нет в официальном репозитории?

там жёсткие требования к 3rd library

BigForceGun
16.11.2011, 21:02

xandeadx
Это вы про phpquery?
А library api ?
Или лень?

phpquery, codemirror.
library api тут не при чём

BigForceGun
16.11.2011, 21:10

Вы извините, что надоедаю, но интересно просто.
А что тогда за требования(думал то, что в составе идти не должны - вот и ляпнул про Library api, что бы сами закачивали)?

всё правильно, все сторонние библиотеки должны ставится самостоятельно. Library api просто детектит их наличие и ничего более.

А как можно сделать так:
Пропарсил сайт, ноды сохранились все в порядки.
Нашел второй сайт, нужно с этого сайта, только в одно поле писать, уже созданных нод.

Гость
04.12.2011, 23:26

На странице Оставляется ссылка со спарсенной странице, что: Материал спарсен со страницы:....
Подскажите, зачем там в ссылку вшит anonym.to ? , что бы прямой ссылки на материал не было? И что подставить вместо anonym.to лучше ?

Гость
06.12.2011, 20:40

А как мне запускать парсинг например по ссылке?

Гость
06.12.2011, 21:22

Ну по сути то как то ж наверно можно все таки...типа соединиться по curl и скриптом нажать на кнопку или еще как нить...нет?

А сколько бы стоило внедрить гугл транслейт в парсер?

Забыл спросить, а как можно добавить в крон задание ?

Что бы определенное задание работало по крону

Гость
19.06.2012, 15:05

День добрый, модуль выше всяких похвал. Один вопрос возник, уж очень быстро есть дисковое пространство, может есть какие то временные файлы или таблицы которые можно почиститить за модулем?

Гость
19.06.2012, 15:18

/sites/default/files/parser_cache/ ?
Можно без болезнно удалять все?

Виктор
09.02.2013, 11:28

Классный модуль! Чутку его переписал, и отпарсил все шаблоны фритемплейтс ит. Вот http://www.juicestudio.ru/ в разделе шаблоны. Теперь буду пользоваться только им,ибо ранее изобретал велосипеды :). Нужно добавить возможность задержки времени между запросами и подключение через прокси и будет вообще кайф.

задержка появилась в последних коммитах

Николай
13.02.2013, 14:59

установил модуль parser 2, все вроде хорошо но вот только как его настроить так чтоб спарсировать вот эту страницу http://www.restoran.ru/msk/catalog/restaurants/all/, помогите пожалуйста уже несколько дней бьюсь, то картинки не отоброжаются, хотя и загружаются на сервер, то одно то другое не получается, замучился, я в php не силен, зарание благодарен!

Гость
17.02.2013, 20:17

Здравствуйте xandeadx, спасибо за отличный модуль.

Я ставлю его уже второй раз, до этого устанавливал давно и все отлично работало, но сейчас возникает данная ошибка: "Notice: Undefined index: properties in _parser_get_entity_properties() (line 1642 of E:\Web\sites\all\modules\xandeadx-parser-dfeac08\parser.module)". Я предполагаю, что это связано с новыми версиями PHP, из-за них уже много обсуждений на оф. форуме PHP и Drupal'а. Или, может быть, я что-то не правильно делаю... Подскажите пожалуйста, что это может быть.

Гость
17.02.2013, 20:59

Спасибо (всего за пять минут!), теперь все работает, но не отображаются никакие поля кроме RemoteID, переустанавливал модуль и проверял в двух браузерах

Гость
17.02.2013, 21:06

Извиняюсь, это из-за модуля UUID (хотя странно, что он повлиял).

Гость
17.02.2013, 23:16

Спасибо, он мне нужен был чтобы экспортировать контент с одного сайта на другой, но зачем это все, если есть Parser)

Подскажите еще пожалуйста, вот например для поля Image нужно возвращать массив с file и alt, а можно ли как-то расширить это, чтобы указывать еще и $title (в смысле аттрибут img 'title')? В Parser'е искал, не нашел чтобы там alt для изображений где-то был указан. Это не существенно, так как после парсинга наверное это не сложно будет сделать через БД из alt, просто интересно

Гость
17.02.2013, 23:23

В настройках поля Drupal'а включен, при редактировании созданного материала можно указать

Гость
17.02.2013, 23:33

Спасибо большое, просто не знал где искать.

И, еще хотел сказать, раз есть такая возможность: если в структуре материалов нету поля body, то при сохранении и/или выполнении тоже возникает ошибка про "Undefined index: body", но стоит добавить поле body и все начинает работать. Сейчас использую парсер с Hidden полем body, после вашего ответа думаю, что это наверное тоже из-за Entity

...И issue там очень похожий на это есть

Гость
18.02.2013, 00:20

Да, теперь все работает без body, спасибо

Гость
25.02.2013, 05:11

Здравствуйте еще раз, xandeadx

А из-за чего может возникать предупреждение при парсинге: "Strict warning: Only variables should be passed by reference в функции eval() (строка 2 в файле E:\Web\www\sites\all\modules\parser\parser.module(710) : eval()'d code)."?

Существенно ли это? Я парсю изображения с файлового хостинга, и некоторые из них странно выводятся после парсинга: в оригинальном размере отображаются правильно, а в измененных размерах не отображаются (и даже не создаются). Кажется, это предупреждение и проблема с изображениями возникает когда в названии содержится знак процента.

Гость
25.02.2013, 05:37

...хотя теперь это наверное уже не актуально, т.к. без прокси они блокируют доступ даже с задержками. Интересно, можно ли PHP-запросы пустить через Tor

Гость
01.03.2013, 04:02

А как правильно спарсить форум? Предположим, пользователей можно создать заранее (они, кстати, не парсятся, кажется там недостаточно полей, в частности нет поля пароля), темы форумов парсятся хорошо, а как сделать ответы в теме, чтобы если отвечал один и тот же пользователь — сообщения создавались так же от одного пользователя? Можно, например, при парсинге одной страницы запомнить переменную имени пользователя так, чтобы к ней был доступ при парсинге другой страницы? И как на одной странице с ответами на форуме распарсить каждый ответ в отдельный комментарий? И если мы уже спарсили главное сообщение темы, то для ответов необходимо указывать его по ID, и получается, что если необходимо создавать все комментарии в одной теме, надо знать ее ID, вместо того чтобы просто спарсить и сравнить названия... (это чтобы сразу несколько тем парсить)

Наверное, настолько все автоматизировать невозможно, но знать хотя бы как из одной страницы сделать несколько материалов/комментариев?

чтобы если отвечал один и тот же пользователь — сообщения создавались так же от одного пользователя?

поле author

Можно, например, при парсинге одной страницы запомнить переменную имени пользователя так, чтобы к ней был доступ при парсинге другой страницы?

поле remote id

И как на одной странице с ответами на форуме распарсить каждый ответ в отдельный комментарий?

включите режим списка

Добрый день.
Первым заданием парсера нужный контент получен. Сейчас появилась задача устанавливать на сайте такие цены, как на источнике.
Попробовал создать новое задание,в дополнитеольных параметрах "Не обновлять сущности" чек бокс не установлен.
В журнале ошибка парсера при сохранении, что логично:
Ошибка при сохранении сущности: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ' 94047' for key 'sku'

Как обновлять/возможно с помощью парсера?

более удобного варианта нет для обновления лишь одного поля?

заполните код только для одного поля

заполните код только для одного поля

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

подскажите,почему после обновления файлов модуля не проходит update.php(с ошибками)
перед обновлением:

ОЖИДАЕТСЯ 9 ОБНОВЛЕНИЙ
parser module

7203 - Add new col to {parser_jobs}
7204 - Rename {parser_map}.page_key to {parser_map}.remote_id
7205 - Add new col to {parser_jobs}
7206 - Remove col from {parser_urls}
7207 - Increase size of fields
7208 - Add index in {parser_urls}
7209 - Add new cols to {parser_jobs}
7210 - Remove and add cols in {parser_jobs}
7211 - Add new col to {parser_jobs}

После запуска update.php

http://pastebin.com/7d5qgyGk

и заходе на страницу заданий появляется ошибка
http://pastebin.com/hfx80bJW

переустановите модуль

отключить в модулях удалить, и обратно?
пробовал так ...не помогало...ещё раз попробую - о результате отпишусь

прекрасный модуль, а не подскажите, что прописать: в "PHP код для поля The main body text" , чтобы при парсинге удалялись внутренние ссылки на другую страницу внутри текста.

Спасибо большое!
И еще если Вас не затруднит, последний вопрос =) :
Как очистить Html-код от пробелов,
1. что прописать: в "PHP код для поля The main body text"

2. и что прописать: в Field "field_categories", если нужно материал при парсинге присвоить родительскому термин к примеру taxonomy/term/55

Заранее благодарен, с уважением Олег!

Спасибо! Правда с очисткой пробелов так и не получилось разобраться ну ладно. =) Всплыл, еще один вопрос наверное это относительно - Парсинг списков.
1.Если на странице и внутри текста несколько фотографий, который хотелось бы все спарсить , что прописать в "PHP код для поля Showcase Image" , чтобы добавилось несколько фотографий.
Showcase Image - это галерея фотографий.
Возможно ли это =)?
2. ссылка на спарсиной странице ведущая на оригинал видна только с правами админа. Как это побороть, чтобы видели все пользователи =)
Заранее благодарен. Пока реклам ку на сайте посмотрю ;)

1. если нужно в одно поле записать несколько фото, то режим списка вам не нужен. Смотрите дефолтное задание.
2. добавьте соответствующее поле

дефолтное - знать мне бы еще как это =)
вот по этому скрипту

$images = array();
foreach ($doc->find('img') as $b) {
$images[] = substr(pq($b)->attr('src'), 4);
}
return $images;

показываются все фотки но ничего при парсинге не грузиться

а вот при таком скрипте

return array(
'file' => $doc->find('.pic img:first')->attr('src'),
);

грузится но только одна, самая первая фотка в тексте для парсинга.

как быть =( ?

Николай
22.07.2013, 09:52

Подскажите пожалуйста как правильно спарсить поле даты, сделать его системным

что значит "сделать его системным"?

Николай
22.07.2013, 18:02

Имел ввиду парсить не в текстовое поле а в поле дата?

Николай
22.07.2013, 18:14

не могу понять нужно ли еще для етого добавлять поле data в тип материала?

Николай
22.07.2013, 18:32

спасибо, все облазил, не знаю как мог это упустить)

Гость
19.11.2013, 05:30

Здравствуйте, спасибо за отличный модуль. Всю ночь пытаюсь разобраться с обновлением существующих нод...

Я спарсила ноды, сделала им Remote ID. Как в другом задании обновлять уже созданные ноды? Я пока смогла только так (в постобработке):

$wrapperForUpdate = entity_metadata_wrapper('node', parser_get_entity_id_by_remote_id('RID'));
$wrapperForUpdate->title = $entity->title;
$wrapperForUpdate->save();

Но чувствую что это неправильно, в частности потому, что парсер все равно своим entity_wrapper'ом новые ноды создает. Пыталась вставлять ID ноды в $entity, в $entity_wrapper вообще ничего не вставляется... Подскажите, как правильно?

Гость
19.11.2013, 18:02

Тогда сделаю пока $entity->nid = ИД обновляемой ноды, чтобы новые не создавались... А вообще, если кому это интересно, наверное надо еще проверять, есть ли уже такая нода, а то насоздается...

Гость
07.12.2013, 23:02

Доброго вечера господа.
Просьба не ругать а как парсить сайт с такой структурой .

тут пусто

тут контент

Как прописать парсинг span уже стал настройювать .

Михаил
27.12.2013, 03:43

Каким запросом осуществлять парсинг элементов без атрибутов, например:
Жирным выделено то, что необходимо спарсить, остальное - нет

<p>
Some text <br>
Some text<br>
Some text<br>
</p>

<p>
Some text <br>
Some text to parse <br>
Some text to parse<br>
</p>

В приведенном выше примере <p> 2 абзаца можно так и идентифировать по порядковому номеру, но как парсить строки внутри <p>? А задача еще сложнее - отдельные слова внутри строк. Есть ли в PhpQuery запросы для идентификации номера строки и номера слова? Или просто - как сформировать запрос, чтобы спарсить "text to parse" и "text to parse" из приведенного выше примера?
Сам парсер отличный - огромное спасибо!

Михаил
27.12.2013, 13:46

Не могли бы Вы привести пример для парсинга text to parse из второго <p> посредством регулярных выражений. Спасибо!

Михаил
27.12.2013, 14:02

Задача такая - еще раз:
Есть страница на чистейшем html - вот ее часть:

<p>
Some text <br>
Some text<br>
Some text<br>
</p>

Some text <br>
Some text to parse <br>
Some text to parse<br>

Из всего текста выделено жирным то, что нужно спарсит, то есть только текст: text to parse.
Вопросы:
1. как это сделать с помощью регулярных выражений - с примером если можно
2. возможно ли идентифицировать номер внутри конкретного

, по аналогии с p:last?

Михаил
27.12.2013, 14:03

В вышеприведенном коменте вторая часть текста тоже между <p></p>

Михаил
27.12.2013, 14:14

То есть return $doc->preg_match('#Some (text to parse)<br>#')?

Михаил
27.12.2013, 14:16

Глупость написал - return $doc->preg_match('#Some (text to parse)<br>#')
не пройдет - как на PhpQuery подобное сделать?

Михаил
27.12.2013, 14:20

И все-таки можно ли идентифицировать <br> чем-то вроде br:last - я не нашел как, но возможно решение есть?

Добавить комментарий