xandeadx.ru Блог музицирующего веб-девелопера

Drupal → Parser 2

Допилил до более-менее рабочего состояния вторую версию парсера. Основные отличия:

  • Парсить можно в любые сущности зарегистрированные на сайте — ноды, термины, пользователи, комментарии, товары и т.д.
  • Работа с сущностями ведётся с помощью Entity metadata wrappers.
  • Поддержка всех, доступных для записи, свойств сущности — автор, статус и т.п.
  • Все файлы, скачанные парсером, сохраняются в кэше (public://parser_cache) и при повторном парсинге берутся из него.

Модуль не совместим с первой версией, поэтому перед установкой анинсталим её, удаляем папку с модулем и устанавливаем вторую версию.

Прямая ссылка на скачку последнего снапшота Parser 2.

Если отписываете о найденных багах, то обязательно прикладывайте экспорт задания.

Написанное актуально для Drupal 7
Похожие записи

Комментарии RSS

И еще вопросик как заполнить 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, в другом 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

Можно как то прикрутить прокси?

есть страницы с урлами вида: 'сайт.рф/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, каждый из которых "превращать" в ноды?

нет

Как работать с датой
Вот массив который мне нужно вернуть

array(
  'value' => $value, // Дата начала (date, optional)
  'value2' => $value2, // Дата окончания (date, optional)
)

Но он дата не вставляется
пробовал даже так
return array (
'value' => '2013-10-10 00:00:00',
  'value2' => '2013-10-10 00:00:00',
);

местами менял ничего не выходит

дата должна быть в формате timestamp

Большое спасибо автору модуля за его работу!
Подскажите пожалуйста, пару моментов:
1) При создании сущностей нодов есть поля таксономии с множественным значением и в интерфейсе парсера написано:

PHP код, который должен вернуть массив значений поля (array(значение1, значение2, ...)) (тип: list).

Что имеется ввиду - массив имен терминов или массив tid терминов таксономии (термины уже занесены в базу)?

2) То же самое, но при однозначном поле таксономии. В интерфейсе парсера написано:

PHP код, который должен вернуть значение поля (тип: taxonomy_term).

Что имеется ввиду - имя термина или его tid?

3) И аналогичный вопрос относительно автора ноды. Написано:

PHP код, который должен вернуть значение поля (тип: user).

Что там вносить - имя пользователя или его uid?
Заранее спасибо за ответы!

в терминах можно возвращать как имя термина, так и tid. в пользователе - uid

Спасибо за ответ, однако, я там, где множественные поля решил вставлять массивы с именами терминов, а там где одиночные, вставил tid, так множественные поля заполнились верно, а вот там где tid передавался насоздавалось терминов с названиями типа 161, 206 и т.д. Хотя по номерам я проверил - термины с такими tid на сайте у меня уже были. В чем же дело? Может надо было преобразовать строки типа "161" в int?

И еще вопрос - после неудачного запуска задания, в котором создавались сущности-ноды, были созданы новые ненужные термины, если теперь нажать reroll кнопку парсера для данного задания, то эти ненужные термины не уберутся?

1. нужно возвращать число, а не строку
2. нет

Как можно использовать счётчик?
Нужно в поле вставлять значение счётчика пропарсенных в данном задании сущностей.

$context['sandbox']['created_entities']

На странице, которую распарсиваю есть вкладки (у вкладок свои урлы)
Урлы вкладок я могу получить через _parser_get_page_by_url().

Вот только пока не понял, а как затем вытащить данные на странице вкладки?
Как сообщить parser что нужно взять распарсенные данные на странице по другому урл.

Получается, что в ноду пишется и собираются данные с разных страниц.

$doc1 = _parser_create_phpquery(_parser_get_page_by_url(урл));
$doc2 = _parser_create_phpquery(_parser_get_page_by_url(урл));
...

У модуля есть пара бага/фитчей, из за которых часто непонятно почему при проверке в задании все работает, а при реальном парсинге появляются ошибки.

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", в журнале ошибка

Ошибка при записи в $entity_wrapper->parent: Invalid data value given. Be sure it matches the required data type and format.
Value:
AUDI

и родитель не создается

родитель должен уже существовать

В том то и дело он существует. Я его ручками добавил ).

В поле "Родительские термины (parent)" пишу

return "AUDI";

Это правильно?

скорей всего нужно возвращать tid термина

Та же самая ошибка... (

если тип list, то логично предположить, что на вход требуется массив

Подскажите, пожалуйста.
Парсим товар с сайта по категориям. Т.е. руками в таксономии указываем например return 5 (tid). Т.е. все товары будут принадлежать термину 5.
Потом парсим товары из другой категории на исходном сайте и у нас указываем return 6 (tid другой категории). И получаем следующее создано 50 сущностей и 30 обновлено.
Заходим в категорию 5 и там вместо начального кол-ва товаров на 30 меньше. Т.е. товары из 5 категории перешли в 6.
Подскажите как можно сохранять принадлежность к терму и при парсинге дописывать значения, а не переписывать их. Т.е. 30 товаров из должны принадлежать и 5 категории и 6.

отметьте опцию "не обновлять сущности"

Как можно при php запуске конкретного парсера передать ему массив ссылок страниц для парсинга?

$job = parser_job_load(123);
$job->start_url = implode("\n", array(ссылки));
parser_job_save($job);

Хочу с использованием модуля 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), также не пойму в какой стадии писать изменение...

Если пишешь в body remove, то в image уже становится элемент не доступен..

делайте clone

Спасибо за подсказку, но где мне делать clone? Если в body, то смысла нет, все равно надо будет убить картинку, если в image то там уже не доступна она....

перед тем, как модифицируете $doc

Попробовал так в body

$r = $doc->find('.featured-image-inner img:first');
$c = pq($r)->clone();
$doc->find('.featured-image-inner img:first')->remove();
 
return array(
  'value' => $doc->find('.entry-content')->html(),
  'format' => 'full_html',
);

в image

return array(
  'file' => pq($с)->attr('src'),
);

Не работает.

из $doc не надо ничего удалять, удаляйте из клонированного объекта.
$doc один на все поля

Столкнулся с такой проблемой, переношу контент на сайт, который раньше был обновлен с 6 на 7. Проблема с форматом текста. Т.е. в примере указано:

return array(
  'value' => $img,
  'format' => 'full_html',
);

А у меня машинное имя формата Full HTML не 'full_html' а '2'. Пробовал так:

return array(
  'value' => $img,
  'format' => '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 у меня все работает, появилась задача на существующий проект спарсить.

Решил в базе поменять значения, и все стало ок.

UPDATE field_data_body SET body_format = REPLACE( body_format,  '2',  'full_html' )

И еще в таблицах
filter
filter_format

Заменил.

Намекните, как пройти авторизацию? Например на стандартном SMF форуме?

curl или drupal_http_request

Ок, получилось авторизоваться через пост. По крайней мере при тестовом запросе, этот код выводит авторизованную страницу:

$post_data = array('user' => 'ХХХ,'passwrd' => 'ХХХ','hash_passwrd' => '');
$result = _parser_post_request('http://manya.org/index.php?action=login2', $post_data, array('max_redirects' => 10));
print $result;

Но почему-то при парсинге сессия не сохраняется?

Маленькая помарка, там не 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,}}}}

не понимаю о чём вы

Доброго вечера!

Подскажите, как при парсинге файла, задать ему имя и расширение?

array(
  'file' => $file, // Файл изображения. (file, required)
  'alt' => $alt, // Текст атрибута "Alt" (text, optional)
)

Наверное тут "(file, required)", через required как-то можно?

$cache_uri = _parser_download_url_to_cache(url_файла);
$file = _parser_copy_file($cache_uri, '/path/to/file.ext');
return array('file' => $file->fid);

Спасибо!!

Вопрос в продолжение темы.

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

Вопрос как правильно удаляются подобные файлы??
Уже не в первый раз с этим сталкиваюсь..

$cache_uri = _parser_download_url_to_cache(url_файла);
$file = _parser_copy_file($cache_uri, '/path/to/file.ext');
return array('file' => $file->fid);

Радость была не долгой :(
Данный метод имеет один существенный недостаток.
Парсинг с помощью "_parser_download_url_to_cache" происходит без учета кода предварительной инициализации (авторизации)!

В первый раз сработало потому что авторизованные страницы уже были в кеше, т.к. ранее файл запрашивался стандартным методом:

array(
  'file' => $file, // Файл изображения. (file, required)
  'alt' => $alt, // Текст атрибута "Alt" (text, optional)
)

Понял, правильно так:
$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)

Нужен совет:
при парсинге получаю PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '6222' for key 'PRIMARY'

в базе смотрел нод с таким nid нет то есть почему она возникает?
Почему так происходит не понимаю.

Не знаю глупый вопрос или нет, но задать хочется:
Когда ждать сиё чудо для Drupal 8!? А то и темы коммерческие уже появляются.
Это очень сложно? А то у меня есть простенькие сайтики ещё на 5-ке :-)
Вот и наконец то решился их перенести так уж на 8-ку! :-)

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

Александр, большая человеческая просьба!
Как можно обнаружить что парсер берет не тот entity id. уже дня 4 не приходит решение.

при парсинге получаю PDOException: SQLSTATE[23000]:
Integrity constraint violation: 1062 Duplicate entry '6222' for key 'PRIMARY'

Я удалял ноды через Content-> хотя есть функция rollback для уже напарсеных в самом парсере. Может в этом причина что сбился счетчик, хотя брать его парсер должен из базы,

может есть путь debuginga, или намек где копать? Может бывает такое, когда я $page_url вписываю как Remote_id

Ваш опыт профессионала очень ценен и я готов перечислить сумму для развития, Спасибо

я не знаю причину появления ошибки

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

1. Задача минимум. Как сделать эту ссылку на источник материала видимой для анонимов?

2. Задача максимум. Как сделать эту ссылку видимой для анонимов и при этом добавить к ней атрибут "rel=nofollow" и чтобы ссылка ссылалась на некий скрипт (модуль) на моём сайте (т.е. для поисковых ботов была внутренней, а не внешней), а уже скрипт бы её перебрасывал через анонимайзер на страницу источник материала?

Спасибо.

получите url с помощью _parser_get_url_by_entity_id()
выведите url в своём node.tpl.php

Решение: свой Rules который пересохранял ноду - получалось реально дубль пытался сохранить, хотя в моем понимании это не один и тот же момент и ошибки быть не должно.
Была ошибка: PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '***' for key 'PRIMARY'

Код для поля изображения, проверяющий загружаемые изображения на предмет их наличия на нашем севере.

То есть позволяет избавиться от дубликатов изображений.

Логика работы:

1) Загружаем в кеш проверяемое изображение.
2) Ищем в указанной папке на нашем сервере такой же файл путем сравнения md5 хешей.
3) Если находим дубль, находим его идентификатор (FID)
4) Передаем FID существующего файла.

foreach ($doc->find('a.images') as $a) {
  $file = pq($a)->attr('href');
  // $file = str_replace('resize/', '', $file);
 
  // Загружаем в кеш изображение для дальнейшего сравнения
  $cache_uri = _parser_download_url_to_cache($file);
 
  // Папка на нашем сервере в которой будем искать изображения для проверки
  $dir = "public://images/";
 
  // Получаем массив с картинками из указанной директории
  $drupal_files = file_scan_directory($dir, "/.*\.(jpg|png|gif)$/");
  foreach ($drupal_files as $drupal_file) {
 
    // Сверяем md5 загруженной картинки с md5 каждого из изображения из указанной папки
    if (md5_file($drupal_file->uri) == md5_file($cache_uri)) {
      $filename = $drupal_file->filename;
    }
  }
 
  // Если идентичный файл был найден, получем его FID по названию файла
  if (isset($filename)) {
    $query = new EntityFieldQuery();
    $result = $query->entityCondition('entity_type', 'file')
      ->propertyCondition('filename', $filename)
      ->execute();
      $file_object = reset($result['file']);
      $file = $file_object->fid;
  }
 
 $images[] = array(
  'file' => $file,
  'alt' => pq($a)->attr('alt')
 );
}
 
return $images;

Александ, а как можно создать-клонировать parser через php со своими изменениями. Пытался поменять jid на новый и сохранить через entity_save не сохраняет, и нового в списке не появляется. entity_create выдает ошибку. по функциям не нашел?

смотрите parser_install() в parser.install

Ну никак не могу получить дату )

Код

return $doc->find('div.data11')->text();

возвращает
2015-02-23 12:10:02 +0300

А дата все равно сейчашняя..

Так тоже не катит
2015-02-23 12:10:02

Скажите а можно как то из источника получить url название статьи и присвоить ее создаваемой ноде?

Что бы url остался тот же?

не понимаю вопроса

Не знаю как тут расписать все, вот на дурпал ссылка
http://www.drupal.ru/node/115937
Я там описал проблему, она конечно индивидуальна, но может что-то подскажешь.

Спасибо.

Это вообще возможно?
В момент парсинга брать url .html к примеру страницы с которой парситься и вставлять в алиас создаваемой ноды?

отметьте опцию "Сохранять адреса"

Александр,
1) Есть ли возможность останавливать процесс через php parser_run_in_background($jid); или проверять его статус что например осталось 10 из 30 допарсить?
2) а функция parser_run_in_background($jid); продолжает парсинг или начинает его заного? и как продолжить (функция php) если уже запускался парсер?
3) можно ли выполнить свой код после заверения работы парсера parser_run_in_background($jid); ?

Спасибо за полезный модуль!

1) нет
2) начинает заново. parser_run_batch($jid, FALSE, TRUE);
3) нет

отметьте опцию "Сохранять адреса"

У меня истерика....
Всего??
Я настолько не внимателен что неделю мучаюсь?
facepalm...

XandedX еще раз огромное человеческое СПАСИБО..

Еще 1 маленький вопросик.
У меня уже есть 5000 перенесенных новостей парсером, и я в перенесенных уже в 100-200 что-то правил.

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

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

Спасибо огромное вам за ваши труды, а самое главное за то что вы не просто написали клевый модуль, а еще и отвечаете людям это достойно уважения по моему!

Отписал тут
http://www.drupal.ru/node/115937#comment-636358

Еще раз ОГРОМНОЕ спасибо, я перенес более 20 000 новостей, с 4 сайтов в совокупности, не потерям при этом ничего, в том числе и URL!

Добрый день

Планируете ли добавление поддержки metatag ?

пока нет

Даже не смотрели что там ?

Может есть какие-то мысли ?

Можно было бы совместно ускорить доработку.

Давно парсером не пользовался, но помнится, там есть предобработка - в самом низу добавляемого шаблона - думаю там можно добавить соответствующие данные для полей!?

Подскажите пожалуйста, а как сохранять количество просмотров используя статистику из ядра ?

Столкнулся с небольшой проблемой, может быть её решение может стать доп. фичей такого классного модуля.

Проблема:
Парсим данные "списком". При парсинге страниц через n запросов на странице выводится капча (в соседней вкладке браузера её вбиваешь и продолжается разбор). Так вот, парсер собрал большую базу основных страниц и создал сущности только с тех, где не было капчи. Как теперь экономно пройтись по неудачным страницам?

Вариант решения:
1. обратиться к данным задания и узнать какие адреса обработаны в "Original URL"
2. проверять url страницы (как в белом списке) с помощью php, чтобы его не было в обработанных. Эта проверка отличается от "Код проверки для дальнейшего парсинга страницы" тем, что страница не загружается, а проверяется только её адрес.

То есть, сейчас пришлось для повторного прохода взять адреса

select url from parser_map where jid = 3 group by url;

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

Можно было бы подключить антигате API и распознать капчу. Но мудуль вообще то для официального парсинга, а не для граббинга ;-)

"Код предварительной инициализации" - вот здесь бы иметь возможность: skip_url, parser_stop

Имеется несколько урлов в "Стартовый URL". Как у спарсенной сущности узнать, по какому из этих урлов ее нашли?

_parser_get_url_by_entity_id($entity_type, $entity_id, $jid = NULL)

Это немного не то. Это адрес самой сущности на стороннем сайте. Мне нужен адрес страницы, с которой модуль перешел на эту страницу )

Например, в стартовом урле страница http://xandeadx.ru, задание парсить все ноды, модуль найдет все страницы и спарсит их и _parser_get_url_by_entity_id вернет адрес http://xandeadx.ru/blog/drupal/554, а мне нужен получить адрес http://xandeadx.ru.

такой информации модуль не хранит

Подскажите как обрабатывать файлы без разрешения вида http://bimobject.com/en/content/showproductimage?id=078f4126-2f43-4188-9...
проверка return array( 'file' => $doc->find('img')->attr('src') ); дает урл но картинка не загружается

Спасибо, работает

А можно запретить создание ноды если title или body пусты?

возвращайте FALSE в "Код проверки для дальнейшего парсинга страницы"

НЕ могу сообразить что вписать в поле:
PHP код для поля Родительские термины
В примечании хоть и есть подсказка, но час уже бьюсь не знаю что вписать.
PHP код, который должен вернуть значение поля (тип: list<taxonomy_term>).

массив идентификаторов родительских терминов

Да это понятно. Но можно образец?

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

return array(123);

Спасибо за ответ. Я думал как-то сложнее указывается )

Почему-то не срабатывает этот код.

$images = array();
foreach ($doc->find("table table td[width='100%'] a")->attr('id') as $b) {
$images[] = (pq($b)->attr("href"));
}
return $images;

Если убираю из него ->attr('id'), то все работает.
Или если писать $doc->find("table table td[width='100%'] a")->attr('id') вне цикла, то тоже работает.
Весь мозг сломал, не понимаю в чем дело. Все же правильно записано.

метод attr возвращает строку, а не объект phpQuery

Спасибо большое.
Переправил строку так:
($doc->find("table table td[width='100%'] a[id]")

Еще вопрос:
Можно ли указать в какую папку сохранять изображения?

укажите путь в настройках поля

Там можно задать только фиксированный путь. Токены связанные с текущей нодой не работают. Вместо урла или заголовка, возвращается "Batch".

Проблема в том что на сайте доноре все картинки имеют одно название, но находятся каждая в своей папке.

Большое спасибо.
Изучу.

Здрасте. Очень нужна помощь. Все хорошо парсица, но мне надо связать Карточку товара с товаром в DC. Я так понял там в поле prod_reference должно быть значение SKU товара. У меня на одну карточку товара, может быть несколько товаров. Я использую этот код:
$prods = array();
//вытаскиваю то что нужно
foreach ($doc->find('div.kod-tov p') as $a) {
//Изюавляюсь от букв, оставляю лишь числа в SKU функцией eregi_replace
$int = pq($a)->text();
$prods[] = eregi_replace("([^0-9])", "", $int);
}
return $prods;
Ошибок нет, я не совсем понял описание поля, внизу: "PHP код, который должен вернуть массив значений поля (array(значение1, значение2, ...)) (тип: list)" .
Подскажите, как исправить, пожалуйсто.

возвращать нужно идентификаторы товаров, а не артикли

При парсинге сайта не требующего авторизации выдаёт ошибку:

Ошибка при закачке "****": Internal Server Error, Результат: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru"> <head> <link href="/bitrix/cache/css/s1/eshop_blue_copy/template_2a0baf5dbb9a28b826dfac1395bd1251/template_2a0baf5dbb9a28b826dfac1395bd1251_1e5c8172e35c0206a58de4c3c0dcec7a.css?143050916763161" type="text/css" data-template-style="true" rel="stylesheet" /> <link rel="stylesheet" type="text/cs

Попробовал в браузере - всё нормально, в текстовом браузере lynx такая же ошибка 500, но потом после подтверждения приёма cookie: PHPSESSID=1f2bo2un63mplb03omd8hv70l0 Принять? (Y/N/A)Всегда/V)Никогда) открывает страницу.

Вижу выше написано про cookie:
В первый код добавляем:

$result = _parser_post_request('****', [], array('max_redirects' => 0));
if (preg_match('#PHPSESSID=(.+?);#', $result->headers['set-cookie'], $matches)) {
	variable_set('parser_data_PHPSESSID', $matches[1]);
}

В Код предварительной инициализации? Сделал.

В HTTP заголовки:

Cookie: PHPSESSID=[parser_data_PHPSESSID]

Но всё равно - 500. Что не так?

Добавлю.

Вот, что выдал код

return $result = _parser_post_request('****', [], array('max_redirects' => 0));

stdClass Object
(
    [request] => POST **** HTTP/1.0
Content-Type: application/x-www-form-urlencoded
User-Agent: Drupal (+http://drupal.org/)
Host: ****
Content-Length: 0
 
 
    [data] => тут содержимое страницы
 
 
 
    [protocol] => HTTP/1.1
    [status_message] => Internal Server Error
    [headers] => Array
        (
            [server] => nginx/1.6.2
            [date] => Tue, 16 Jun 2015 16:23:37 GMT
            [content-type] => text/html; charset=UTF-8
            [connection] => close
            [x-powered-by] => PHP/5.3.3
            [p3p] => policyref="/bitrix/p3p.xml", CP="NON DSP COR CUR ADM DEV PSA PSD OUR UNR BUS UNI COM NAV INT DEM STA"
            [x-powered-cms] => Bitrix Site Manager (DEMO)
            [set-cookie] => PHPSESSID=t1jjuu4qiclu85an6qk8onech5; path=/; HttpOnly
            [expires] => Thu, 19 Nov 1981 08:52:00 GMT
            [cache-control] => no-store, no-cache, must-revalidate, post-check=0, pre-check=0
            [pragma] => no-cache
            [x-frame-options] => SAMEORIGIN
        )
 
    [geshifilter-code] =&gt; 500&#10;    [error] =&gt; Internal Server Error&#10;)&#10;
[/geshifilter-code]

смотрите какие заголовки отправляет php, я к сожалению не телепат

Как это посмотреть?

поставьте любой снифер

В настройке «Задержка между http запросами» — установлено 15 секунд.

Но за минуту создалось около 30 нод.

Какая причина может быть этому?

Скрин результата парсера

кэш

Создаются дубли нод. И записывается в БД одинаковый remote_id
Я даже не знаю в какую сторону смотреть, с чем может быть связано. У Вас есть предположение?

P.S.

кэш

Понял.

Создаются дубли нод. И записывается в БД одинаковый remote_id
Я даже не знаю в какую сторону смотреть, с чем может быть связано. У Вас есть предположение?

Отключил проверку по ID — парсер прошел без дублей.

На каждую новую ноду в логах появляется предупреждение:

Warning: Invalid argument supplied for foreach() in _parser_set_property() (line 1555 of /home/admin/web/nb.sitiq.ru/public_html/sites/all/modules/parser-master/parser.inc).

Warning: Invalid argument supplied for foreach()

Предупреждение (Warning) — из-за моего поля изображений.

Дубли пока создаются — ищу выход.

Создаются дубли нод. И записывается в БД одинаковый remote_id

Дубли создаются при включенном фоновом запуске.
Крон - каждые 9 минут
Парсер - каждые 600 сек.
Как считаете нормальные настройки?

Еще вопрос:
Как остановить парсер запущенный в фоне, без удаления задания?

Добрый день. справится ли этот модуль с парсингом товаров на яндекс.маркет?
Мой заказчик оказался человеком креативным и из 1с грузятся только артикулы а характеристики нужно парсить с яндексмаркета и цеплять к нодам.
XadndeadX , Поможет ли мне Ваш модуль в моем вопросе?

навряд ли

Добрый день.

Парсил товары и после ноды товаров.
Все 900 товаров залились, ноды связаны - всё хорошо.

Но после перехожу в список заданий и вижу, что с заданием по загрузке товаров связано всего 500 товаров (SELECT COUNT(*) FROM `parser_map` WHERE `jid`=7 => 500). Запускаю задание заново и появляются ошибки:

Ошибка при сохранении сущности: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1916' for key 'sku'. Адрес: ***
Value:
stdClass Object …

При этом:
SELECT COUNT(*) FROM `commerce_product` WHERE 1 => 900 (товаров)
SELECT COUNT(*) FROM `parser_map` WHERE `jid`=3 => 900 (нод)

Что-то ломается в таблице parser_map?

Пробовал очищать таблицу commerce_product, и начинать всё заново - после задания по парсингу нод товаров слетает таблица parser_map для задания по товарам.

Пробовал пару раз так.

Что это может быть?

В документе есть изображения, и путь к каждому изображению разный. Что-то типа такого:

<img src="/dir1/dir2/dir3/image.jpg">
<img src="/dir1/dir5/dir7/image2.jpg">
<img src="/dir1/dir2/image3.jpg">

Как заменить путь на свой для всех изображений?

Второй день голову ломаю:
Вот так например не работает:
$value = str_replase(($doc->find('img[src]')->html()), 'mypath', $value);

foreach ($doc->find('img') as $img) {
  $src = pq($img)->attr('src');
  $src = str_replace('from', 'to', $src);
  pq($img)->attr('src', $src);
}

Здравствуйте. Как можно парсить зависимые фильтры на странице. например как на skinon.ru

У сайта-донора часть ссылок включают в себя запятые. Из-за этого парсер выдает ошибки, не может их увидеть.
Можно ли как-то это обойти?

Как установить язык, значение типа token?

где установить?

В поле Язык, задания на парсинг.
Например установить "Русский" для всех импортируемых сущностей.

return 'ru';

Получится? Ведь это не token.

Почему-то нода становится с ru, а поля все с und языком.
Как сделать и поля с ru?

Сайт донор имеет url'ы такого вида: /svetilniki-pod-lampu-nakalivanija-bytovye-(npo,-nbb,-nvo).html т.е. содержит запятые. Из-за них парсер не может скачать эти страницы.
Что можно с этим сделать?

Посмотрел внимательнее - url'ы с запятыми все-таки читаются. Но непонятно почему некоторые страницы не скачиваются. В журнале такая запись:

Ошибка при закачке "http://domain.ru/katalog/svetilniki/svetilniki-pod-lampu-nakalivanija-bytovye-(npo,-nbb,-nvo).html": missing schema
Remote URL: http://domain.ru/katalog/svetilniki/svetilniki-pod-lampu-nakalivanija-bytovye-(npo,-nbb,-nvo).html

Всё, разобрался в чем проблема была. Часть ссылок была с .html на конце, хотя на самом деле страницы на которые ведут ссылки без .html.
Решил проблему подправив файл parser.inc. В 1694 строке добавил:

$href = str_replace('.html' , '/', $href);

Перед:
$href = preg_replace('/#.*$/', '', $href);

В поле body я заменяю путь ссылок на свой:

foreach ($doc->find('img') as $img) {
  $src = pq($img)->attr('src');
  $dir = dirname($src);
  $src = str_replace($dir, '/sites/default/files/imgsvet', $src);
  pq($img)->attr('src', $src);
}

Но этот код меняет объект, и т.к. поле body стоит выше поля Image, то и изображения пытаются скачаться по новому пути. Из-за этого ошибка.
Как поставить поле Image перед Body, чтобы парсер сначала создавал массив ссылок, а затем обрабатывал Body?
Иногда после очистки кеша, у меня в парсере менялся порядок полей, не знаю с чем это связано. Image оказывался перед Body, и изображения скачивались без проблем. Специально повторить это у меня не получается.

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

Ваш модуль парсинга неоценим. Очень хорошая работа. У меня маленький вопросс: Не настраевается поле с ценой. Я использую код:
return array(
'amount' => 1233,
'currency_code' => 'USD'
'data' => array(),
);
Как это настроить? Спасибо.

что вы хотите настроить?

Я хочу настроить поле цены (price) в сущьносте товара на Commerce.

скопируйте ваш код, вставьте в поле

Вот весь код поля:
$price = $doc->find('#id_prod_price')->text();
$price = preg_replace("/[^0-9]/", '', $price);
return array(
'amount' => $price,
'currency_code' => 'USD'
'data' => array(),
)

в массиве запятой не хватает

Не помогло c запятой. А у вас нет примера заполнения поля прайс? любого. В комментарии к полю написано:
array(
'amount' => $amount, // Количество (decimal, optional)
'currency_code' => $currency_code, // Валюта (text, optional)
'data' => $data, // Данные (struct, optional)
)
Я не знаю что можно записать в 'data'?

Разобрался с полем цена (price) для сущьности товара в Commerce:
Должно быть:
return array('amount' => $price, 'currency_code' => 'UAH', 'data'=>array(),);

Добрый день, пользуюсь вашим модулем довольно давно. Модуль супер. Начал недавно делать новый сайт на связке Дру7 + ubercart 3. Встала необходимость парсинга товаров с другого сайта. Парсятся хорошо все поля кроме Артикула и цены, они просто не забиваются в карточку товара. Подскажите как мне их туда запихать??? Я так понимаю им нужно задать тип значения, т.к. в парсинге ясно сказано "PHP код, который должен вернуть значение поля (тип: decimal)." Подскажите пожалуйста как вернуть значение с этим типом.... Сам код у меня такой:
$price = array();
foreach ($doc->find('.styled_table tbody tr td') as price) {
$price[] = pq($price)->text();
}
return $price[4];

Ладно... По какой причине не добавляются изображеня? тоже самый Юберкарт. код такой:
array(
'file' => $doc->find('#product_info_image img')->attr('src'),
);

Результат выполнения такой:
Array
(
[file] => /images/products/common/3208.jpg
)

Все работает как бы) но при начале работы парсинга, сразе же выдает ошибку:
Возникла AJAX HTTP ошибка. Полученный код HTTP: 500 Следует отладочная информация. Путь: /batch?render=overlay&id=393&op=do Текст Состояния: Service unavailable (with message) Текст Ответа: EntityMetadataWrapperException: There can be only numerical keyed items in a list. в функции EntityListWrapper->get() (строка 989 в файле /sites/all/modules/entity/includes/entity.wrapper.inc)

Как с этим быть, код для парса изображений использую везде. А тут не выходит в чем причина?

Попробуйте:
Return Array
(
[file] => /images/products/common/3208.jpg,
)

$images = array();
$images[] = array(
  'file' => $doc->find('#product_info_image img')->attr('src'),
);

Прошу прощения я так и пробовал
Return Array
(
[file] => /images/products/common/3208.jpg,
);

Парсинг ошибку пишет.... хотя на другом сайте такой код работает. Может ли быть так что версия jquery не та?

> There can be only numerical keyed items in a list.
Это значит, что у вас поле из нескольких значений, а ваш код для одного.

Спасибо за постоянные ответы, мне очень приятно. Я знаю что это означает. Но разве это имеет значение? у меня создается массив изображений. И разве это имеет значение сколько их 1 или несколько?

Выставил одно значение для поле с изображением, изображения стали парситься. А что делать с полям цена и артикул? я не понимаю почему они не забиваются в анкету товара? Есть идеи?

Но разве это имеет значение? у меня создается массив изображений. И разве это имеет значение сколько их 1 или несколько?

Конечно имеют, Друпал их по разному хранит :-)

А что делать с полям цена и артикул?

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

Можно по подробнее?

Читайте описание поля и тут комментарии, где это уже проговаривалось.

Хорошо разберусь, спасибо за наводку. Помогли частично решить проблему)

Не могу сообразить, проштудировал все ответы на страницы. Хандед подсказал использовать в пост обработке: $entity->model = $sku; Но я как это сделать немогу понять. Помоги плз... уже бомбит :)

Разобрался, на друпал 7 меньше года работаю, почитал про entity и сразу догнал, спасибо за помощь ребята.

Здравствуйте! Часть страниц при парсинге выдавали ошибку. Опытным путем вычислил, что это страницы, имеющие часть адреса в кириллице.
Пример страницы: http://ruslanglyantsev.ru/ezoterika/Молодой-да-старый
Парсер выдает ошибку, что страница не найдена:

Ошибка при закачке "http://ruslanglyantsev.ru/ezoterika/Молодой-да-старый": Not Found, Результат: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>ПРОИЗВЕДЕНИЯ | Страница не найдена</title>....

Возможно кто-то сталкивался с такой проблемой? Или есть простое решение без изменения адресов на исходном сайте. Спасибо!

Можно ли в качестве "Remote ID" указывать URL страницы?
Если да, то как?

Дело в том что на странице есть возможность указать заголовок в качестве "Remote ID", но есть вероятность что заголовок изменится.

Спасибо за парсер.

return $page_url;

Спасибо, xandeadx, за классный модуль!
Он мне заменил почти весь Datacol.
Скорость работы просто супер!

Нужна помощь, а именно, в поле field_tags не додумался как правильно написать алгоритм, чтобы указать термин таксономии "Услуги"

Пишу следующее:

$terms=Услуги;
return $terms;

Начинаю парсить, но термин таксономии не привязвается к спарсенным нодам.

Как написать правильно, чтобы к ноды приняли термин "Услуги" ???

Делал новостной агрегатор и надо привязать к нодам уже созданные термины таксономии, такие как, Политика, Культура, Спорт, Экономика и т.д.................

return 'Услуги';

Привет!
Подскажите, как из http://pastebin.com/QxMM7jXe выдернуть значения latitude и longitude с помощью phpquery? возможно такое?

preg_mach('/"latitude":(.+?),"longitude":(.+?),/', $page, $matches);

Я не программер, сложно разобраться, как спарсить сразу несколько картинок в поле изображение? Как я понимаю нужно использовать foreach, но как там дальше не въезжаю, буду признателен за помощь.

Сейчас код выглядит так:
return array(
'file' => $doc->find('.productPhotosList ul li a')->attr('href'),
);

Естественно когда в настройках поля ставлю несколько изображений происходит ошибка.
Когда одно изображение, тогда все работает.

Разобрался, спасибо Psyh! Прочитал внимательнее и заработало. И тебе спасибо xandeadx за модуль, мега-крутая штука!!!
Сделал так:

$images = array();
foreach ($doc->find('.productPhotosList ul li a') as $b) {
$images[] = (pq($b)->attr("href"));
}
return $images;

Да и такой вопрос еще, настраивал на другом сайте и у меня картинки каким то образом которые находяться в статье тоже скачивались, но настроил на другом и почему то не подхватывает. Я так и не понял в чем прикол, можете объяснить?

Уже 3 часа долблюсь не могу понять как мне product соединить с product display.
На той странице, на которой я парсю товары есть артикул, его я достаю при парсинге product, вот так: return $doc->find('#qproduct_id span')->text();

Потом при парсинге Product display я в поле товара вставляю этот же код, при парсинге он не вставляет в это поле артикул и все. Как я понимаю там нужно использовать list, но как это сделать я понятия не имею в PHP не волоку. Таже пробовал с помощь parser_map нифига не понял как.

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

в поле надо возвращать id товара, а не sku

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

PHP код, который должен вернуть массив значений поля (array(значение1, значение2, ...)). Каждое значение должно быть в формате:

array(
'file' => $file, // Файл. (file, required)
)

return array(array('file' => 0)); не помогает. Надо узнать сколько значений было в существующей ноде, и передать такой массив с пустыми значениями?

Или как научить парсер обнулять поле перед записью?

Добрый день! Я пытаюсь спрасить сайт с видео youtube, но мне надо засунуть их в поле типа "файл", с виджетом Media и модулем Media: oEmbed.
В справке парсера к полю выдается подсказка что надо вернуть такое:

array(
  'file' => $file, // The file. (file, required)
)

Я с страницы выдираю URL видео, передлываю в короткую ссылку:

$url = $doc->find('.entry iframe')->attr('src');
$urlParts = parse_url($url);
$videoId = explode('/', $urlParts['path']);
 
 
return ['file' => "https://youtu.be/$videoId[2]"];

Но таким макаром не работает, в логах:

Файл "https://youtu.be/EsXIWbf1Z1c" закачан не будет, так как его тип "" не в списке допустимых.

Видимо для медия модуля есть хитрость, не сталкивались? Спасибо.

Вот нашел решение, подправил _parser_prepare_field_file полный ответ тут - http://dru.io/question/5902

/**
 * Prepare field type "file"
 */
function _parser_prepare_field_file(&$result, $field_info, $field_instance, $entity, $job, $base_url) {
  if (isset($result['type'])){
 
    $file = $result['file'];
 
    $fileScheme = file_stream_wrapper_uri_normalize('oembed://' . drupal_encode_path($file));
    $fileObject = file_uri_to_object($fileScheme);
 
    $info = media_oembed_get_data($file);
 
    if (!empty($info['title'])) {
      $filename = truncate_utf8($info['title'], 255);
    }
 
    $fileObject->filename = $filename;
    $file = file_save($fileObject);
    $result['file'] = $file->fid;
 
  } else {
   пошел старый код....
}

Ну а в задаче парсинга поля сделал так

$url = $doc->find('.entry iframe')->attr('src');
$urlParts = parse_url($url);
$videoId = explode('/', $urlParts['path']);
 
$file .= "https://youtu.be/";
$file .= $videoId[2];
 
return ['file' => $file, 'type' => 'oembed'];

Добрый день! Подскажите пожалуйста! Как сделать чтоб не создавались товары с одинаковыми названиями (проверить на уникальность) и если уже есть товар с таким названием просто обновить его (если нужно).

Привет! как можно вывести блок со ссылкой, откуда спарсена страница при DS?

сделайте запрос в таблицу parser_map, выведите адрес

Привет! Подскажи как пропарсить страницу, если контент на ней загружается после загрузки страницы?

_parser_get_page_by_url(url)

Спасибо, но не работает
return $doc_parser_get_page_by_url(url)->find('.title')->text();
Подскажите где ошибка? или как правильно прописать?

Реально модуль классный и если немного разобраться в API Drupal то практически получится тот же известный Aparser ток без многопотока.
Пишу может кому то пригодиться такая инфа сам просто мучался долго итак есть поле стартовая страница в нее можно указать не более 65 535 символов но когда урлов много и маску невозможно указать че делать?
Заходим в phpmyadmin находим таблицу: parser_jobs -> структура -> start_url меняем значение text на longtext ! Все добавляем но не более 4 294 967 295 символов.

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

залогинитесь в поле "Код предварительной инициализации"

Спасибо! Не заметил сразу. Отличный модуль, с виду сложный, но с подсказками и примерами разобраться очень просто.

Простите, это опять я. Как спарсить картинки, если у них не указано в ссылке расширение (картинки в cdn)? При парсинге выходит сообщение: Файл "такой-то" закачан не будет, так как его тип "" не в списке допустимых. ?

Здравствуйте. Можно ли сэмулировать паузу после захода на страницу, т.е. закачать страницу еще раз после того, как парсер побыл на ней секунд пять? А то она подгружается Ajax'ом это время...

В drupal commerce может возникнуть такая ошибка:

Integrity constraint violation: 1062 Duplicate entry '1916' for key 'sku'

Нужно заменить код:

/**
 * Add row in {parser_map} table.
 */
function _parser_map_save($record) {
	db_merge('parser_map')
		->key(array('entity_id' => $record['entity_id']))
		->fields(array(
			'jid' => $record['jid'],
			'url' => $record['url'],
			'element' => $record['element'],
			'remote_id' => $record['remote_id'],
		))
		->execute();
}

На:

/**
 * Add row in {parser_map} table.
 */
function _parser_map_save($record) {
	db_merge('parser_map')
		->key(array('entity_id' => $record['entity_id'], 'jid' => $record['jid']))
		->fields(array(
			//'jid' => $record['jid'],
			'url' => $record['url'],
			'element' => $record['element'],
			'remote_id' => $record['remote_id'],
		))
		->execute();
}

Это связано с тем что в двух парсерах (один для продукта, другой для ноды) могут пересекаться entity_id и заменяться на новые. Нужно добавить второй уникальный параметр к key в db_merge.

P. S. Модуль супер.

Александ, я создал свою cущность, но свойства сущности не видны для настроек, можете подсказать что сделать чтобы модуль увидел? Спасибо

http://www.drupalcontrib.org/api/drupal/contributions!entity!entity.api.php/function/hook_entity_property_info/7

Проблема с кирилическими ссылками в разметке сайта, парсинг валится с ошибкой, как решить?

Парсер хороший, но возникает много вопросов. Например - как закрыть от парсинга маской страницы типа www.название-сайта/название-категории/название-статьи/comments ? Дело в том, что комментарии к статье - на отдельной странице, и верстка страницы статьи и верстка страницы с комментариями к статье похожи (аналогичные тэги). Как решить проблему?

Чёрный список адресов: */comments

2 xandeadx Спасибо! Не думал что так просто! А как сделать такую вещь - превратить все ссылки в спарсенном тексте в обычный текст?

Привет!
подскажите, если страница в режиме списка, только заголовок, а картинка и инфа подгружается Ajax-ом по ссылке Подробнее. Как имитировать такое нажатие в парсере?

подскажите, если страница в режиме списка, только заголовок, а картинка и инфа подгружается Ajax-ом по ссылке Подробнее. Как имитировать такое нажатие в парсере?

Непонятно получилось ))
На странице отображается заголовок сущности и кнопка Подробнее, нажав на которую появляется допинфа, которую тоже надо парсить.

С помощью модуля никак не имитировать. Пользуйтесь drupal_http_request().

И снова про замену ссылок в спарсенном тексте на обычный текст. Пытаюсь использовать регулярные выражения. Пишу:

$alltext = $doc->find('div.b-article__body')->html();
foreach($doc->find('div.b-article__body a')->html() as $a) {
$b = pq($a)->text();
$alltext = preg_replace($a, $b, $alltext);
}

$textbody = array(
'value' => $alltext,
'format' => 'full_html',
);

return $textbody;

При парсинге вываливаются ошибки типа Warning: Invalid argument supplied for foreach() в функции eval() , ссылки текстом не заменяются. Конечно можно примитивно скрыть ссылки поставив у поля формат filtered_html но это не выход.

Не работает(( После включения модуля сразу белый экран на всём сайте и в админке в том числе((

2 Влад
Не хватает оперативной памяти сервера, правь хтаксесс.

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

Спасибо за модуль! Подскажите, как правильно обновиться с 7e059b3 на 9849857? Перезалил файлы, но пропал PHP код для полей.

Да, update.php не запускал, а запустив получил вот такое и парсер не пашет: PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'base.proxies' in 'field list': SELECT base.jid AS jid, base.title AS title, base.start_url AS start_url, base.test_url AS test_url, base.only_this_domen AS only_this_domen, base.depth AS depth, base.parse_limit AS parse_limit, base.white_list AS white_list, base.black_list AS black_list, base.check_code AS check_code, base.save_url AS save_url, base.no_update AS no_update, base.site_charset AS site_charset, base.charset_fix AS charset_fix, base.entity_type AS entity_type, base.bundle AS bundle, base.remote_id_code AS remote_id_code, base.fields_code AS fields_code, base.list_mode_code AS list_mode_code, base.init_code AS init_code, base.prepare_code AS prepare_code, base.headers AS headers, base.proxies AS proxies, base.force_download AS force_download, base.force_download_list AS force_download_list, base.sleep AS sleep, base.run_period AS run_period, base.last_run AS last_run, base.status AS status, base.module AS module FROM {parser_jobs} base WHERE (base.status IN (:db_condition_placeholder_0, :db_condition_placeholder_1, :db_condition_placeholder_2)) ; Array ( [:db_condition_placeholder_0] => 3 [:db_condition_placeholder_1] => 2 [:db_condition_placeholder_2] => 6 ) в функции EntityAPIController->query() (строка 187 в файле .../public_html/sites/all/modules/entity/includes/entity.controller.inc) Можете подсказать?

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

Выключил модуль, но анисталить не стал, удалил папку и залил новую- обновление базы прошло без ошибок. Структура на месте, парсер работает. xandeadx, еще раз спасибо за отличный модуль!

xandeadx, у меня еще несколько вопросов к вам:
Есть ли какое-то решение для этого: http://xandeadx.ru/blog/drupal/554#comment-13871 ?
Второй вопрос: как перенести результаты парсинга из одного задания в другое с сохранением Remote ID, Original URL и т.д.? Оба задания парсились в одну и ту же сущность, пересечений нет. Поменять jid в parser_map будет достаточно, чтобы задание "восприняло" спарсенные сущности за свои? Обязательно ли менять parser_urls?
И еще, сюда напишу наблюдение, по поводу http://xandeadx.ru/blog/drupal/561 есть подозрение, что не парсятся картинки если донор на https. Заранее спасибо!

1. Перед сохранение сущности удалите значения из поля
2. Попробуйте

Я извиняюсь за беспокойство, но обнаружилась проблема: не импортируются задания в последней версии. Вернее импортируются, но поля с php кодом остаются пустые. Проверено на разных сборках, разных хостингах. Предыдущую версию тоже проверил - с ней все ок. Как бы починить?

Отличный модуль. Не могу только понять как взаимодействовать с полями типа материала "Товар" модуля UberCart 3. Такими как Артикул и Цена. Я так понимаю это нужно в постобработке делать?

Спасибо за прекрасный модуль!

Появился вопрос:
парсинг прерывается и в логах наблюдаю вот такую ошибку:
"Ошибка при записи в $entity_wrapper->field_category: Invalid data value given. Be sure it matches the required data type and format. Value at node()->field_category:"

Array
(
    [464] => Велосипеды
    [465] => Карбоновые велосипеды
)

я использую вот такой код
return parser_create_terms_hierarchy($terms,10);
Он работает отлично, создает термины в иерархии.
Но почему ошибка?
предполагаю что функция «parser_create_terms_hierarchy» занимается созданием терминов и пытается создать термины, но они уже существуют, нет?

Вот полный код по полю «категория»:

$terms = array();
foreach ($doc->find('#CatNavi .Current a') as $a) {
  $terms[] = pq($a)->text();
}
if (empty($terms)) {
return false;
} else {
return parser_create_terms_hierarchy($terms,10);
};

1. Если поле пустое, то надо возвращать NULL, о чём написано в описании, а не false.
2. Если поле может содержать только одно значение, то надо возвращать id или имя термина, а не массив, о чём тоже написано в описании к полю.

Спасибо, теперь понял в чем ошибка!

проверка return array( 'file' => $doc->find('img')->attr('src') ); дает урл но картинка не загружается

http://xandeadx.ru/blog/drupal/554#comment-10508

пост 10508 отсутсвует а проблема таже

Подскажите пожалуйста. Парсеры работают отлично. Вопрос в следующем. Не могу их импортировать. Делаю экспорт и на том же сайте вставляю код, меняя jid, они подгружаются, но только без скриптов php. Пробовал плагином от np++ менять коды на символы - вообще отказывается загружать.

обновите модуль

Можно ли очистить директорию 'parser_cache' до того как парсер полностью спарсил?
Чем это чревато?

можно

Парсер может работать с полями типа field_collection? Всячески пытаюсь передать значение для заполнения поля, все безрезультатно.

Добрый день! Модуль великолепный, огромное спасибо.
Но возникла следующая проблема, не запускаются несколько заданий, только первое, выше видел коллега писал про такую проблему, но ответа не увидел, поэтому повторяюсь.
Может возможно как-то склеить все задания программно в одно, мне по факту всё равно, главное чтобы отрабатывало автоматом, заранее спасибо за ответ

Самопроизвольно удаляется файл *.inc
При переносе содержимого в файл *.module в последствии удаляется он, без ошибок в логах и пр., крайне мистически

Здравствуйте. Подскажите, есть страница с ссылками на статьи из разных категорий, url которых уходит из подуровня начальной страницы. Например, начальная страница: a.ru/b/c, а искомые страницы имеют пути a.ru/d/f/a или a.ru/b/c/s, то есть не подходят под иерархию. Будет ли в этом случае работать парсер? Можно ли настроить его ходить по ссылкам, заключенных в определенные атрибуты?
Спасибо.

Модулю без разницы по каким ссылкам ходить. Ограничить ссылки атрибутами нельзя, только белый и чёрный список.

А можно ли сделать иерархию в поле типа term (ноды)?
вот так:
- term1.1
- - term1.2
- - - term1.3
- term2
- - term2.2
- - - term2.3
...
- term3.1
- - term3.2
- - - term3.3
http://xandeadx.ru/blog/drupal/762 Здесь есть пример иерархии, но только на хлебных крошках, то есть лишь одна длинная иерархия в ноде получается.

Оставить комментарий

Содержимое этого поля является приватным и не будет отображаться публично. Если у вас есть аккаунт в Gravatar, привязанный к этому e-mail адресу, то он будет использован для отображения аватара.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступные HTML теги: <a> <i> <b> <strong> <code> <ul> <ol> <li> <blockquote> <em> <s>
  • Строки и параграфы переносятся автоматически.
  • Подсветка кода осуществляется с помощью тегов: <code>, <css>, <html>, <ini>, <javascript>, <sql>, <php>. Поддерживаемые стили выделения кода: <foo>, [foo].

Подробнее о форматировании