Поиск по блогу

четверг, 27 августа 2009 г.

DOM vs. RegExp on PHP

dom regexp on php
Последние 2 недели было несколько заказов на написание парсеров на PHP. И я за них бралась, в основном за чисто символическую плату, чтобы повариться в PHP-шной кухне, попробовать разные способы парсинга и, заодним, подучиться не на чистом энтузиазме. ;)

Хочу рассказать о своих впечатлениях.

Парсер на PHP — это удобно и менее време- и ресурсозатратно для разработчика. Естественно, если скрипт предназначен только для скачивания какой-либо базы и последующей проверки обновлений. Ни тебе особых интерфейсов, ни тебе всяких ненужных классов: скачиваешь страницу, парсишь, в базу, по кругу. Для многофункционального ПО по-прежнему использую Delphi.

Скрипты удобны для удаленного запуска по расписанию (не забудьте установить set_time_limit(), чтобы скрипт не останавливался, не доработав до конца).

Когда-то я спрашивала читателей блога, чем удобнее парсить, регулярками или через библиотеку DOM. Тогда прозвучал только один конкретный ответ. Что ж, зато у меня был повод самостоятельно потестировать разные инструменты. Что могу сказать по поводу того, каким способом удобнее парсить html? Чаще всего я все-таки использовала регулярные выражения, потому что привыкла, наверное. Пару раз использовала комбинированный метод: сначала большой табличный кусок "добывала" регуляркой, а потом уже эти хорошо структурированные данные разбирала через DOM.

Чем неудобна библиотека DOM? Тем, что она все-таки не очень хорошо разбирает данные, если они невалидны. Если у вас включено отображение ошибок (php_value display_errors 1), вы можете легко убедиться в этом, взяв произвольный ресурс и попробовав загрузить его страницу в dom-объект

$dom->loadHTML($html);


Выдается список ошибок: то неизвестный тэг, то точка с запятой лишняя, то еще какая-нибудь фигня.

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

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

вторник, 25 августа 2009 г.

С прошедшим днем рождения, блог! :)

Оказывается, этому блогу уже год! Поздравляю себя от имени себя, что у меня хватило мужества его не забросить :) Первая запись была опубликована здесь 20 августа 2008 года. Думаю, что он проживет еще не один год. Задумок для публикации очень много, даже уже есть несколько заготовок, нуждающихся лишь в небольшом причесывании. Но сегодня новой публикации не будет — очень много работы навалилось.

Хочу еще выразить благодарность людям, присылающим мне свои списки RSS-агрегаторов. Как только разгребу дела — обязательно выложу новый конфиг.

И благодарю за информационную поддержку автора блога OnLife.me, который, кстати, собирает на своем блоге список блогов (сорри за масло масляное) для обмена постовыми. А так же авторов блогов news-i.net и Grand Блог. Спасибо-спасибо!

Еще немного запоздалое "спасибо" Владу. Начинающим "делфёрам-парсингёрам" обязательно читать его блог "Delphi в Internet"! :)

Если кто-нибудь еще ставил ссылки на RSSAdder — отметьтесь, пожалуйста, с меня ссылка ;) А то в блоггере нет надежного инструмента для мониторинга обраток.

Для меня этот опыт выкладывания в паблик небольшой бесплатной утилитки оказался очень полезным. Сделала для себя определенные выводы и все такое :)
___

На сегодня это все. Возвращаюсь к работе :)

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

четверг, 20 августа 2009 г.

Еще обновление списка RSS-каталогов

В конфиг добавлено еще 10 каталогов.
21 http://search.yahoo.com/mrss/submit
22 http://content.mail.ru/cgi-bin/list.cgi?action=rss_add
23 http://www.kanban.ru/add.asp
24 http://www.asteria.com.ua/kms_blog+add.html
25 http://www.arkadia-ko.com/kms_blog+add.html
26 http://www.seo-box.com/kms_blog+add.html
27 http://www.sevrealty.com/kms_blog+add.html
28 http://blogrider.ru/catalog/blogs/add
29 http://rss-farm.ru/catalog.aspx
30 http://elite-consult.com/index.php?nma=blog&fla=add


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

Решила не постить сюда обновление в текстовом виде, а просто выложить свежий конфиг (5 Кб), в котором все 30 ресурсов (когда скачаете, информацию о своей RSS возьмите из вашего INI-файла, а то там моя по умолчанию).
___

А сама я, тем временем, неторопливо готовлю статьи для новичков про cURL и парсинг на PHP (с примерами и все такое) :)
___

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

среда, 19 августа 2009 г.

Расширение списка RSS-агрегаторов

Выкладываю конфиги еще для 10 агрегаторов. Как вам их добавить? Просто открываете файл RSSAdder.ini любым текстовым редактором и дописываете их в конец файла (если вы самостоятельно ничего не добавляли к тем десяти агрегаторам, которые там были, — нумерация не нарушится).

вторник, 18 августа 2009 г.

Упс.

В RSSAdder-е был глюк, пропустила при тестировании :( Но он обнаружился и был исправлен. Извините, если уже скачали, — я нечаянно. :) Выложила новый вариант (там в INI добавила еще 2 RSS-каталога, сейчас их стало 10). В предыдущем посте ссылку тоже исправила.

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

понедельник, 17 августа 2009 г.

RSSAdder — добавление RSS в список RSS-агрегаторов

Хочу выложить свою простенькую программку, которая поможет вам упростить регистрацию RSS-ленты вашего блога в RSS-агрегаторах. Я когда-то уже писала о ней. А недавно извлекла из архивов, немного переработала и добавила несколько полезных функций.

Интерфейс программы сейчас выглядит следующим образом:


Все настройки хранятся в INI-файле: это и информация об RSS (если вы ее сохраните), и список RSS-агрегаторов. Список агрегаторов хранится в следующем виде:

[SITExx]
url=
field_url=
field_rss_url=
field_rss_name=
field_dsc=
field_keys=
field_email=
key_delimiter=


[SITExx] - RSS-агрегатор, где xx - номер по порядку
url - ссылка на страницу добавления RSS-ленты
field_url - поле "URL сайта"
field_rss_url - поле "URL RSS"
field_rss_name - поле "Название RSS/сайта"
field_dsc - поле "Описание сайта"
field_keys - поле "Ключевые слова"
field_email - поле "Email"
key_delimiter - разделитель ключевых слов

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

Сначала введите в шапке формы данные о своей RSS-ленте и о блоге.

Чтобы добавить RSS в каталог из списка, расположенного в левой части формы, надо дважды кликнуть на нужном элементе списка. В WebBrowser загрузится форма, в которой будут заполнены поля в соответствии с данными в шапке и данными о названиях/id полей в ini. Вам остается только довводить недостающие параметры (рубрики, капчу и т.д.) и нажать сабмит. Если регистрация в каталоге состоит из нескольких шагов, то после заполнения всех полей вам придется самостоятельно перейти к следующему шагу. Если на следующем шаге от вас требуется заполнение полей, предусмотренных в настройках, то вы можете просто нажать форму "Заполнить форму".

Еще из нововведений:
- рядом с каждым полем сделала кнопочку "Копировать в буфер", на всякий случай :)
- если вы редактируете список агрегаторов в INI-файле, то после его сохранения можно обновить данные в списке не закрывая программу, а просто нажав на "Обновить список из INI"
- добавила закладку HTML Form Viewer для удобства исследования новых RSS-каталогов. Если вы нашли новый каталог, то введите URL для добавления ресурса в строку в верхней части формы, нажмите "Загрузить". После этого загрузится форма, а внутри каждого инпута типа "text" и "textarea" будут подписаны их name и id.



Вам останется только впечатать эти названия в форму в нижней части и нажать "Сформировать код". И в memo появится запись, для добавления в INI-файл, составленная по шаблону. Не забудьте изменить "xx" в строке "[SITExx]" на номер по порядку в соответствии с ранее добавленными записями, а потом дописать полученный результат в свой INI-файл.

У меня к вам есть просьба. Я включила в INI-файл 51 RSS-агрегатор — это мой посильный вклад в формирование списка. Сейчас — ваша очередь. присылайте настройки для новых каталогов на емейл momkarla@gmail.com или оставляйте в комментах. Я буду собирать и выкладывать обновленный список у себя на блоге.

Скачать RSSAdder (1.1 Mb) (в комплектации — 51 RSS-агрегатор).
Редакция от 24.08.2010: Скачать последнюю версию INI-файла (82 агрегатора). На случай, если кто-то скачивал более раннюю версию программы и нужен только "свеженький" конфиг. После скачивания замените INI-файл в папке с программой, оставив свои данные о блоге.

У кого проблемы с Яндексом :) — качайте RSSAdder с зеркала.

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

P.S.: У кого есть аккаунт на Sloger.net — проголосуйте, пожалуйста, за новость.
___

Отдельное спасибо за размещение ссылки на этот пост:
автору блога "Заметки молодого блоггера"
___

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

понедельник, 10 августа 2009 г.

Парсинг HTML на PHP

Потихоньку изучаю возможности PHP для создания парсеров. Я уже писала о том, как парсить xml на php с помощью SimpleXML. Сейчас расскажу об одном из способов парсинга html (он подойдет и для xml тоже, кстати). Повторю, что в php я не гуру, поэтому буду очень признательна, если вы оставите свои комментарии к поднятой теме.

Побродив по нашим и англоязычным форумам, поняла, что спор о том, лучше ли парсить html регулярными выражениями или использовать для этих целей возможности PHP DOM, является холиваром. Сама же я пришла к выводу, что все зависит от сложности структуры данных. Ведь если структура достаточно сложная, то с помощью регулярок приходится парсить в несколько этапов: сначала выделить большой кусок, потом разделить его на более маленькие и т.д.. В итоге, если данные сложные (или их очень много), то процесс парсинга может значительно затянуться. Ресурсоемкость в этом случае еще будет зависеть, конечно же, от самих регулярных выражений. Если в регэкспах много ".*" (они являются самыми ресурсоемкими, т.к. "прочесывают" исходный код с максимальной жадностью), то замедление будет заметным.

И вот как раз в этом-то случае как нельзя кстати приходится PHP DOM. Это удобный инструмент для парсинга как XML, так и HTML. Некоторые придерживаются мнения, что парсить html регэкспами вообще нельзя, и яростно защищают PHP DOM.

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


<?php
$html = '
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<head>
<title>Parsing-and-i.blogspot.com Map</title>
</head>
<body>
<h2>Последние темы блога</h2>
<!-- на 09.08.2009 -->
<table border="0">
<tbody>
<tr>
<td><a href="http://parsing-and-i.blogspot.com/2009/08/blog-post_06.html" title="Базы">http://parsing-and-i.blogspot.com/2009/08/blog-post_06.html</a></td>
<td>Базы</td>
</tr>

<tr>
<td><a href="http://parsing-and-i.blogspot.com/2009/08/mysql-delphi-express.html" title="MySQL и Delphi. Express-метод">http://parsing-and-i.blogspot.com/2009/08/mysql-delphi-express.html</a></td>
<td>MySQL и Delphi. Express-метод</td>
</tr>

<tr>
<td><a href="http://parsing-and-i.blogspot.com/2009/08/blog-post.html" title="Пост о том, что лучше сто раз проверить">http://parsing-and-i.blogspot.com/2009/08/blog-post.html</a></td>
<td>Пост о том, что лучше сто раз проверить</td>
</tr>

</tbody>
</table>

</body>
</html>
';
/** создаем новый dom-объект **/
$dom = new domDocument;

/** загружаем html в объект **/
$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;

/** элемент по тэгу **/
$tables = $dom->getElementsByTagName('table');

/** получаем все строки таблицы **/
$rows = $tables->item(0)->getElementsByTagName('tr');

/** цикл по строкам **/
foreach ($rows as $row)
{
/** все ячейки по тэгу **/
$cols = $row->getElementsByTagName('td');
/** выводим значения **/
echo $cols->item(0)->nodeValue.'<br>';
echo $cols->item(1)->nodeValue.'<br>';
echo '<hr>';
}
?>


В результате после запуска скрипта получаем такую картину:
Parsing html with dom php


Upd: Без всякого сомнения, для более удобной работы со структурой HTML в PHP вам надо познакомиться с библиотекой PHP Simple HTML DOM Parser. Я бы отдала предпочтение именно ей.


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

четверг, 6 августа 2009 г.

Базы

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

База №1
База предприятий с hh.ru (название, описание, сайт, ссылка на профайл на хэдхантере). Формат — MySQL. Сразу напоминаю, база неполная. Сначала запустила парсер глобально, на все регионы, но выкачать всю не удалось — запустила только на Москву. В базе в поле REGION: 0 - предприятия, скачанные по запросу "Все" (в том числе частично и Москва), 1 — стопроцентная Москва (без дублей). Всего 35217 записей. companies.zip Размер: 13,3 Мб.

___

Предлагаю авторам тематических блогов обменяться постовыми. У моего блога ТИЦ20, PR3, DMOZ. Подписчиков на сегодня приблизительно 130. Рассмотрю все предложения с блогов с примерно такими же параметрами.
___

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

вторник, 4 августа 2009 г.

MySQL и Delphi. Express-метод

Парсинг информации о предприятиях закончился. Производился он достаточно долго, так как я никуда не торопилась и поставила двухсекундную задержку между загрузками страниц. Собранную информацию я записала в базу Firebird. И решила по-быстрому перекинуть ее в MySQL, чтобы выложить, как обещала.

В Delphi на работе у меня не установлено ничего для работы с MySQL. Решила попробовать настроить доступ к данным MySQL через ODBC. Получилось довольно быстро и нехлопотно, поэтому решила написать инструкцию и выложить в блоге — вдруг кому пригодится.

1. Скачиваем драйвер ODBC с официального сайта MySQL. На данный момент ссылка на страницу продукта такая: http://dev.mysql.com/downloads/connector/odbc/5.1.html. Пришлось там у них зарегистрироваться, чтобы получить возможность скачать, что надо. Но это дело двух минут — не страшно.

2. Параллельно я создала в MySQL базу, с которой планировала работать (полей там больше, с расчетом на дальнейшую работу)


3. Устанавливаем драйвер
MySQL-ODBC install

4. Идем в Настройки / Панель управления / Администрирование / Источники данных (ODBC) / Системный DSN / Добавить

Настраиваем там подключение.
Congfig MySQL ODBC
Нажимаем на "Test" и Убеждаемся, что соединение проходит.
test config mysql odbc

5. В Delphi.
5.1. Кинуть на форму ADOConnection. Двойной клик на нем, настроить все, что надо. На первой закладке ("Поставщик данных") выбрать "Microsoft OLE DB Provider for ODBC Drivers". На второй закладке у меня получилось следующее (я подключалась к локалхосту :) ):
ADOConnection Config
Опять же, после настройки можно проверить подключение и убедиться, что все работает.
5.2. А дальше все элементарно, просто работать с базой через ADO. Например, поместить на форму ADOTable, назначив ей в свойстве Connection созданный ранее ADOConnection. И так далее.

База, состоящая из 35217 записей (в основном Москва, REGION=1), получилась 35 метров, в архиве 14. Это из-за того, что описания фирм там пространные, типа "мы, такие-то такие-то, ведущий производитель на мировом рынке"... Многовато по размеру, да. Но придумаю, куда выложить, и выложу.

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

понедельник, 3 августа 2009 г.

Пост о том, что лучше сто раз проверить

Подумала я давеча: "Раз уж парсер компаний с хедхантера написан, то почему бы его не запустить?" Взяла и запустила. Проработал он меньше суток, остановился. "Ну, - думаю, - чудненько! Так быстро отпахал!". Но когда посмотрела результаты, записанные в базу, — поняла, что что-то не то, так как данных было гораздо меньше, чем официально "обещали" на сайте. Залезла на хедхантер, полистала страницы вручную. Сначала все шло благополучно и ничто не предвещало беды. Но когда полезла вглубь, то заметила, что списки предприятий не отображаются. Например,
http://hh.ru/employersList.do?&areaId=113&companyWithoutVacancy=on&page=100



На последних страницах списки компаний опять нормально отображаются, как ни в чем не бывало (чтобы убедиться, достаточно поставить page=777). Соответственно, нужно внести корректировки и в алгоритм. Например, просматривать не весь список, а список по отдельным буквам алфавита или по регионам. Но я уже потеряла интерес к этому занятию и переписывать не буду. Единственно, что запустила парсер на компании Москвы, пусть парсит (добавляю в базу, в которой уже было 9 с лишним тысяч предприятий, спарсенных из "общего" списка). Парсинг закончится — выложу базу :)

Что касается таких ситуаций. Если честно, у меня уже второй раз так: начинаю парсить, а потом оказывается, что не учтены некоторые обстоятельства. Первый раз это было из-за того, что заказчик сам неточно составил задание и не учел один тип вывода данных, а я не перепроверила (база была большая, я посмотрела наугад страниц 20 - все удовлетворяли шаблону, а потом выяснилось, что есть группа исключений). Я к тому, что это не страшно, конечно, но на предварительном этапе лучше всегда проводить более тщательные исследования. И всегда быть готовым к "неожиданностям".

Удачных разработок!
___

А еще — попробую добавить свой блог в рейтинг блогов. :)
___

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

Поделиться