Допилил до более-менее рабочего состояния вторую версию парсера. Основные отличия:
- Парсить можно в любые сущности зарегистрированные на сайте — ноды, термины, пользователи, комментарии, товары и т.д.
- Работа с сущностями ведётся с помощью Entity metadata wrappers.
- Поддержка всех, доступных для записи, свойств сущности — автор, статус и т.п.
- Все файлы, скачанные парсером, сохраняются в кэше (
public://parser_cache
) и при повторном парсинге берутся из него.
Модуль не совместим с первой версией, поэтому перед установкой анинсталим её, удаляем папку с модулем и устанавливаем вторую версию.
Прямая ссылка на скачку последнего снапшота Parser 2.
Если отписываете о найденных багах, то обязательно прикладывайте экспорт задания.
Написанное актуально для
Drupal 7
Похожие записи
- Модуль Parser — парсинг сайтов
- Модуль EAV Field — хранение большого числа характеристик сущности в одном поле
- Модуль Background Queue — выполнение всей очереди в фоне
- Модуль Commerce Fast Ajax Add to Cart — ajax кнопка "Добавить в корзину" без кэширования формы
- Модуль Block Visibility by Vocabulary — вывод блока только на страницах терминов определённого словаря
Комментарии
И еще вопросик как заполнить Product SCU (Ubercart) при выборе типа материала Товар, поля артикул не вижу?
в пост обработке:
$entity->model = $sku;
при обновлении источника спарсенная статья не обновляется в чем может быть проблема ?
----разобрался после очистки кеша, а как кеш чистится или обновляется после обновления страницы он меняется или как ? как то в ручную не хорошо чистить постоянно
не обновляется и не чистится
но без очистки страницы не обновляются как быть ?
очищать кэш любым доступным способом
В белом и черном списках можно указывать числовой диапазон для уточнения маски ?
нет
Подскажите, а как решить следующую проблему, на сайте-доноре одно из полей подгружается при клике по элементу с другого урл через js,
<span class="closed" rel="/url">"Нажмите, чтобы увидеть"</span>
, как заставить парсер пройти по /url и выдернуть блок с id="parseinfo"?получите вручную с помощью _parser_get_page_by_url(url)
Как спарсить ноды вместе с комментариями?
В режиме списка есть пример, который работает по кнопке Проверить и действительно возвращает массив комментариев и импортируемого сайта. Но к создаваемой ноде эти комментарии не привязываются.
вместе никак. парсите сначала ноды, потом комментарии
Возникла следующая проблема: при парсинге если поле пустое, то оно все равно отображается в документе, т.е. отображается заголовок и в коде остаются дивы обрамляющие поле, хотя при ручном добавлении материала все нормально.
возвращайте
NULL
, если не нужно заполнять полеТакой вопрос. Если свяжется автор материалов и захочет:
1. Чтобы по материалам с его сайта была активная ссылка на источник, видимая для посетителей. Можно ли как-то разом будет такое сделать (только для его материалов, а остальные с других сайтов остались бы нетронутыми)?
2. Удалить все материалы взятые с конкретного сайта, можно ли это будет разом сделать, чтобы не затронуть остальные, спарсенные с других сайтов?
1. создайте новое поле
2. можно удалять все сущности созданные в конкретном задании. это ссылка rolback в списке заданий
Добрый день, подскажите пожалуйста последовательность действий, как правильно с помощью парсера добавить товары с набором полей и материалы отображения товаров со своим набором полей для drupal commerce, чтобы они связались через поле commerce_product_reference нужное с нужным товаром.
Предполагаю, что сначала надо создать задание для создания сущностей товара и установить remote_id для каждого товара и занести поля, относящиеся к сущности товара. А затем, то ли как в комментарии немного выше указано, вызвать из постобработки другое задание, которое создает сущности отображений товара и заносит поля (которое создается заранее), то ли как то иначе, может даже проще надо делать, не пойму.
Каков все-таки порядок действий для парсинга в drupal commerce? Спасибо.
в одном задании создаёте product, в другом product display
Это я уже понял, не понятно как связать товар с соответствующим product_display. Насколько я понял, после выполнения первого задания где-то хранятся соответствия remote_id и product_id и во втором задании, создающем отображение товара надо в поле product (типа commerce_product_reference) занести значение, которое находится по remote_id такому же, как у текущего элемента.
Вопрос - как получить эти значения из ранее выполненного задания?
читайте описание поля remote id
Спасибо огромное за парсер. Переношу сайт с вп на drupal. все поля парсятся как надо кроме поля даты. из $doc->find('.updated')->attr('datetime'); получаю строку, которую никак не удается передать. пробовал разные варианты:
2013-01-31 14:18:28 +0400
2013-01-31T14:18:28+04:00
2013-01-31
возможно проблема в том, что надо преобразовать строку в тип date. если это так, то намекните пожалуйста как это реализовать. требуется чтобы все старые посты были именно с той датой публикации, которая была у них.
возвращайте timestamp
Можно как то прикрутить прокси?
http://drupal.org/project/http_proxy
есть страницы с урлами вида: 'сайт.рф/news/98127.html' , на многие страницы нет ссылок.
Можно ли каким то образом указать для парсера диапазон страниц для обхода?
Например в поле КОД ПРОВЕРКИ ДЛЯ ДАЛЬНЕЙШЕГО ПАРСИНГА СТРАНИЦЫ :
for ($i=0; $i<=98100; $i++) {
_parser_url_add('http://www.19rus.info/news/'$i'.html');
}
return $doc->find('#full-wrapper .news-content-wrapper')->length() == 1;
в стартовом адресе укажите маску
http://www.19rus.info/news/[mask:0,98100].html
Подскажите, пожалуйста, как правильно возвращать значение для поля с датой в виде timestamp, если на сайте-источнике дата указана в виде d/m/Y ?
strtotime
Здравствуйте. Скажите, а сможет ли Ваш модуль парсить папку и находить в ней файлы *.html, каждый из которых "превращать" в ноды?
нет
Как работать с датой
Вот массив который мне нужно вернуть
Но он дата не вставляется
пробовал даже так
местами менял ничего не выходит
дата должна быть в формате timestamp
Большое спасибо автору модуля за его работу!
Подскажите пожалуйста, пару моментов:
1) При создании сущностей нодов есть поля таксономии с множественным значением и в интерфейсе парсера написано:
Что имеется ввиду - массив имен терминов или массив tid терминов таксономии (термины уже занесены в базу)?
2) То же самое, но при однозначном поле таксономии. В интерфейсе парсера написано:
Что имеется ввиду - имя термина или его tid?
3) И аналогичный вопрос относительно автора ноды. Написано:
Что там вносить - имя пользователя или его uid?
Заранее спасибо за ответы!
в терминах можно возвращать как имя термина, так и tid. в пользователе - uid
Спасибо за ответ, однако, я там, где множественные поля решил вставлять массивы с именами терминов, а там где одиночные, вставил tid, так множественные поля заполнились верно, а вот там где tid передавался насоздавалось терминов с названиями типа 161, 206 и т.д. Хотя по номерам я проверил - термины с такими tid на сайте у меня уже были. В чем же дело? Может надо было преобразовать строки типа "161" в int?
И еще вопрос - после неудачного запуска задания, в котором создавались сущности-ноды, были созданы новые ненужные термины, если теперь нажать reroll кнопку парсера для данного задания, то эти ненужные термины не уберутся?
1. нужно возвращать число, а не строку
2. нет
Как можно использовать счётчик?
Нужно в поле вставлять значение счётчика пропарсенных в данном задании сущностей.
$context['sandbox']['created_entities']
На странице, которую распарсиваю есть вкладки (у вкладок свои урлы)
Урлы вкладок я могу получить через _parser_get_page_by_url().
Вот только пока не понял, а как затем вытащить данные на странице вкладки?
Как сообщить parser что нужно взять распарсенные данные на странице по другому урл.
Получается, что в ноду пишется и собираются данные с разных страниц.
У модуля есть пара бага/фитчей, из за которых часто непонятно почему при проверке в задании все работает, а при реальном парсинге появляются ошибки.
1) Если в одном поле что нибудь удалить через
$doc->find('div')->remove()
, то в следующем поле нельзя будет получить доступа к этим данным при парсинге, хотя при тестировании через "проверить" эти данные можно получить. Т.е. кнопка "проверить" не учитывает код из других полей.2) В каждом задании лучше называть переменные уникальными именами. Не знаю для всех ли полей, но я скопировал код из одного задания (парсинг нод, получение remote id) в другое задание (парсинг комментариев) в поле node (с дополнениями конечно). В итоге кнопка "проверить" показывала нужный результат, а в реальности remote_id для задания комментариев всегда получалось как из задания с парсингом ноды. Долго не мог понять причину, в итоге переименовал переменные в скопированном коде и все заработало.
1) это фича
2) навряд ли
Еще проблема:
Если у поля с файлом (в частности с изображением) настроить путь сохранения файла в определенную папку (например в sites/default/all/products) с помощью Filefield path, то при первом проходе парсера все сохраняется правильно, а при втором и последующих проходах (обновление ноды) файлы сохраняются прямиком в sites/default/all. Тоже самое происходит и при переименовании файлов через Filefield path.
При запуске по крону, если забыть указать ограничение по количеству создаваемых сущностей - парсер будет работать вечно. Помогает только перезагрузка сервера)
Может сделать какой-то однозначный стопор? И галочку и статус в списке парсов тоже было бы удобно, мне кажется.
Есть сайт, с которого надо забрать более 3000 страниц. Парсер запускается по крону каждые 5 минут и успевает обработать 950 страниц (с задержкой 2с), а дальше крон перезапускается и парсер начинает все заново, с первой страницы, т.е. новые сущности уже не успевают создаваться.
Можно, конечно, увеличить время между запусками крона, но если подобных сайтов/заданий для парсера будет 5-10, увеличение пауз не решит вопрос.
Можно ли как-то сделать так, что бы запуск по крону не начинал сначала, а продолжал с того места, где остановился в прошлый раз? А вот когда круг завершится - тогда уже начинать заново, идти от первой страницы, обновлять сущности и т.д. Это бы очень упростило бы парсинг больших сайтов.
зачем вам каждые 5 минут парсить весь сайт? спарсите вручную, в крон поставьте задание забирать только новые страницы
Спасибо, попробую так. Для добавления только новых страниц - достаточно поставить галочку "Не обновлять сущности" или нужно еще что-то?
нужно прописать адреса страниц, на которых появляется новый контент
Добрый день, модуль работает отлично. Только возникла проблема и не могу понять в чем проблема. Вообщем с донора парсим html, но внутри html кода есть div блоки, которые не нужны на выходе. Каким образом можно удалить из html блоки с определенным классом??? jQuery знаю, но remove выдает Fatal Eror....
$doc->find('selector')->remove();
А как можно поставить/снять флаг у новой сущности?
Программно они ставятся легко, но только при наличии nid, а без него - не получается.
А в парсере последний момент - это ровно перед сохранением, после - нет.
Можно с помощью Rules, но не хотелось бы его ставить только ради этого.
У флагов есть настройка - показывать их в качестве полей при редактировании материалов. Может подобным образом давать возможность установить флаги, которые подходят к этому типу материала?
скорей всего только в своём модуле через хук
Уважаемый xandeadx покажите пожалуйста структуру массива термина таскономии с иерархией для парсера.
Как добавлять родительский термин я знаю, а вот как цеплять дочерние? Или это не возможно?
невозможно
А если я буду парсить в сущность термин таксономии? В парсере в настройках полей имеется "Родительские термины (parent)". тип: list, подставляю например "AUDI", в журнале ошибка
и родитель не создается
родитель должен уже существовать
В том то и дело он существует. Я его ручками добавил ).
В поле "Родительские термины (parent)" пишу
Это правильно?
скорей всего нужно возвращать tid термина
Та же самая ошибка... (
если тип list, то логично предположить, что на вход требуется массив
Подскажите, пожалуйста.
Парсим товар с сайта по категориям. Т.е. руками в таксономии указываем например return 5 (tid). Т.е. все товары будут принадлежать термину 5.
Потом парсим товары из другой категории на исходном сайте и у нас указываем return 6 (tid другой категории). И получаем следующее создано 50 сущностей и 30 обновлено.
Заходим в категорию 5 и там вместо начального кол-ва товаров на 30 меньше. Т.е. товары из 5 категории перешли в 6.
Подскажите как можно сохранять принадлежность к терму и при парсинге дописывать значения, а не переписывать их. Т.е. 30 товаров из должны принадлежать и 5 категории и 6.
отметьте опцию "не обновлять сущности"
Как можно при php запуске конкретного парсера передать ему массив ссылок страниц для парсинга?
Хочу с использованием модуля https://www.drupal.org/project/remote_file_source не скачивать оригиналы фоток к себе, но использовать их для превьюшек и тд. Если в поле картинки указать ссылку на файл, то модуль Parser все равно скачает картинку к себе.
Можно ли это как нибудь избежать?
Скажите, а как можно в обратную сторону парсить страницы. Чтобы сначала брало старые материалы а потом более новые сверху и так же их выкладывало на сайт.
нельзя
Столкнулся с проблемами, не соображу как поступить:
1. Есть поле image, его спокойно добавляю
'file' => $doc->find('.featured-image-inner img:first')->attr('src'),
НО, в дальнейшем мне надо его убать из body, иначе будет дубль в ноде, в поле image и в теле. Где лучше его убрать? Если пишешь в body remove, то в image уже становится элемент не доступен..
2. Нужно в body менять путь к остальным изображениям (img src), также не пойму в какой стадии писать изменение...
делайте clone
Спасибо за подсказку, но где мне делать clone? Если в body, то смысла нет, все равно надо будет убить картинку, если в image то там уже не доступна она....
перед тем, как модифицируете $doc
Попробовал так в body
в image
Не работает.
из $doc не надо ничего удалять, удаляйте из клонированного объекта.
$doc один на все поля
Столкнулся с такой проблемой, переношу контент на сайт, который раньше был обновлен с 6 на 7. Проблема с форматом текста. Т.е. в примере указано:
А у меня машинное имя формата Full HTML не 'full_html' а '2'. Пробовал так:
Получаю в логах:
Ошибка при записи в $entity_wrapper->body->format: Invalid data value given. Be sure it matches the required data type and format.
Value:
2
Пробовал передавать число, без кавычек, тоже самое.
Я правильно хоть делаю, что пытаюсь машинное имя передать?
Я передаю машинное имя и все работает. На 6ке были цифры, да, но текущий сайт сразу с 7ки, возможно поэтому такой проблемы у меня не возникает. А какое значение в базе при нормальном, не программном создании поля? В базе вперемешку цифры и машинные имена?
В таблице field_data_body в поле body_format стоят числа. Видно форматы перенеслись с числовыми. В таблице filter_format также в поле format числа. При этом типы полей varchar(255) как и положенно.
На чистой 7 у меня все работает, появилась задача на существующий проект спарсить.
Решил в базе поменять значения, и все стало ок.
И еще в таблицах
filter
filter_format
Заменил.
Намекните, как пройти авторизацию? Например на стандартном SMF форуме?
curl или drupal_http_request
Ок, получилось авторизоваться через пост. По крайней мере при тестовом запросе, этот код выводит авторизованную страницу:
Но почему-то при парсинге сессия не сохраняется?
Маленькая помарка, там не print а return. Но это не влияет на результат.
В общем, непонятно что надо отдать парсеру друпала чтобы он сохранил сессию.
Разобрался!!! /* танцующий смайлик */
В первый код добавляем:
if (preg_match('#PHPSESSID=(.+?);#', $result->headers['set-cookie'], $matches)) {
variable_set('parser_data_PHPSESSID', $matches[1]);
}
Затем созданный нами токен "parser_data_PHPSESSID" используем в HTTP заголовках к серверу (поле в самом низу).
Сори за флуд, и спасибо за модуль! :)
Добрый день, на http://habrahabr.ru/post/164707/ был пример парсинга данных json. Никак не получается приобщить к своему примеру. Подскажите пож-ста, что на что нужно заменить в JsonExampleParser.inc если выгрузка у меня такая
{"success": true, "data": {"HKT":{
"0":{"price":35610,"airline":"UN","flight_number":571,}, "1":"price":27119,"airline":"CX","flight_number":204,},
"2":{"price":33242,"airline":"AB","flight_number":8113,}}}}
не понимаю о чём вы
Доброго вечера!
Подскажите, как при парсинге файла, задать ему имя и расширение?
Наверное тут "(file, required)", через required как-то можно?
Спасибо!!
Вопрос в продолжение темы.
Во время экспериментов, было создано много изображений (без родительстких нод). Если удалить их напрямую с сервера, то в дальнейшем получу кучу ошибок при загрузке файлов.
Вопрос как правильно удаляются подобные файлы??
Уже не в первый раз с этим сталкиваюсь..
Радость была не долгой :(
Данный метод имеет один существенный недостаток.
Парсинг с помощью "_parser_download_url_to_cache" происходит без учета кода предварительной инициализации (авторизации)!
В первый раз сработало потому что авторизованные страницы уже были в кеше, т.к. ранее файл запрашивался стандартным методом:
Понял, правильно так:
$cache_uri = _parser_download_url_to_cache(url_картинки, $job->headers, FALSE);
Привет, помогите советом, парсер работает хорошо, уже пол года пользуюсь, огромное спасибо автору!!! Столкнулся с проблемой, установил чистую сборку (минимум), подключил все что мне нужно и парсер... все парсилось хорошо, без нариканий, и вдруг парсер стал добавлять ноды с дублями картинок, типа xxx.jpg xxx_0.jpg все настройки пересмотрел, модули включал отключал , переустанавливал, не помогает... самое интересное что при нормальном создании нода все номано. Не подскажите куда копать?
дубли создаются при совпадении имён
я понимаю что при совпадении но откуда они берутся, если на фтп нет файлов, кэш чистый... и ещё файл xxx.jpg в текстовом редакторе смотрится как html страница а фаил xxx_0.jpg это исходная картинка
вопрос снимается, проблема дублей была из-за повторных ссылок в BODY , теперь другой вопрос: как в BODY указать глобальную переменную типа $_SERVER['HTTP_HOST'] , что бы при переносе с localhost ссылки автоматом становились типа: domain.com
При создании нового парсера при нажатии сохранить выдаёт ошибку:
drupal_write_record() (строка 7239 в файле /home/cp475123/public_html/домен.ru/includes/common.inc).
Вопрос снимается, решил уменьшением времени автозапуска.
Александр, а есть ли возможность выполнить парсинг с получением значения по 1 url.
То есть на куждую ноду созданную, нужно допарсить с другого url ууникального для каждой ноды, то есть как можно для одного филда ноды допарсить с другого url тут же чтобы не создавать доп контент тайп, views, пересохранение ... ? Спасибо Вам
_parser_get_page_by_url(url)
Добавить комментарий