Парсим iCal. Забрать данные с iCal? Нет ничего проще.

Сегодня мы будем писать скрипт для парсинга различных ресурсов, использующих для передачи данных о событиях файлы в формате iCal. Формат этот был придуман компанией Apple и в настоящее время на многих сайтах вы можете экспортировать события из календаря сайта в этом формате. В этом случае вам не нужно будет скрапить сам сайт и его HTML, а только лишь файл в формате iCal.

Diggernaut нативно поддерживает этот формат и автоматически переводит его в XML. И далее мы можем работать с этими данными также как с обычной HTML страницей.

Давайте посмотрим как это работает на примере календаря Science Fiction Conventions, найденного мной на просторах сайта icalshare.com. Начнем с написания раздела с установками. На первом этапе нам нужно будет установить диггер в дебаг режим с уровнем 2. Только так мы сможем увидеть исходный код забранного нами файла с календарем. А исходный код нам нужен, чтобы написать навигационную логику к блокам с данными, которые мы ходим забрать.

Сам календарь находится по адресу: https://www.google.com/calendar/ical/lirleni%40gmail.com/public/basic.ics

Итак, начало нашего конфига будет таким:

---
config:
    debug: 2
    agent: Firefox
do:
- walk:
    to: https://www.google.com/calendar/ical/lirleni%40gmail.com/public/basic.ics
    do:
        - stop

В этом коде мы устанавливаем уровень Debug в 2, конфигурируем парсер использовать Firefox как имя браузера и забираем iCal файл. Теперь нам нужно зайти в свой аккаунт на Diggernaut.com, выбрать существующий проект (или создать новый) и создать в нем новый диггер, где в качестве конфига использовать вышеуказанный код.

Удостоверимся, что парсер находится в Debug режиме (в колонке Status должно быть указано Debug). Если нет, то нужно перевести парсер в дебаг режим, выбрав его в колонке Status. После чего мы должны запустить его. Как только диггер отработает, мы можем просмотреть лог запуска нажав на соответствующую иконку.

<html>

<head></head>

<body>
    <body_safe>
        <event>
            <alarmtime>0s</alarmtime>
            <class>PUBLIC</class>
            <created>2009-03-07 20:15:36 +0000 UTC</created>
            <description>Gaming Convention</description>
            <end>2011-01-31 00:00:00 +0000 UTC</end>
            <id>2a994c3e3b80f5af6e8fa178a3af45d4</id>
            <importedid>b82f342c-0b54-11de-b762-000d936372a6</importedid>
            <location>Champaign IL (USA)</location>
            <modified>2011-02-20 23:29:49 +0000 UTC</modified>
            <rrule></rrule>
            <sequence>4</sequence>
            <start>2011-01-28 00:00:00 +0000 UTC</start>
            <status>CONFIRMED</status>
            <summary>WinterWar 38</summary>
            <wholedauyevent>true</wholedauyevent>
        </event>
        <event>
            <alarmtime>0s</alarmtime>
            <class></class>
            <created>2009-01-10 17:33:11 +0000 UTC</created>
            <description>Gaming convention</description>
            <end>2011-08-08 00:00:00 +0000 UTC</end>
            <id>5c8f16d772ede097822e73a0c2e51c6c</id>
            <importedid>356F0F0C-FE52-47A8-AEAB-8E78F57D4F52</importedid>
            <location>Indianapolis IN</location>
            <modified>2011-02-20 23:29:48 +0000 UTC</modified>
            <rrule></rrule>
            <sequence>10</sequence>
            <start>2011-08-04 00:00:00 +0000 UTC</start>
            <status>CONFIRMED</status>
            <summary>GenCon</summary>
            <wholedauyevent>true</wholedauyevent>
        </event> ...

Как мы видим структура страницы разбита на блоки . Так что все, что нам остается — это пройти во все блоки event и забрать все поля из каждого такого блока. Итак, давайте выберем один блок и отформатируем его, чтобы было лучше видно какие поля мы будем забирать и какие фильтры будем использовать.

<event>
    <alarmtime>0s</alarmtime>
    <class>PUBLIC</class>
    <created>2009-03-07 20:15:36 +0000 UTC</created>
    <description>Gaming Convention</description>
    <end>2011-01-31 00:00:00 +0000 UTC</end>
    <id>2a994c3e3b80f5af6e8fa178a3af45d4</id>
    <importedid>b82f342c-0b54-11de-b762-000d936372a6</importedid>
    <location>Champaign IL (USA)</location>
    <modified>2011-02-20 23:29:49 +0000 UTC</modified>
    <rrule></rrule>
    <sequence>4</sequence>
    <start>2011-01-28 00:00:00 +0000 UTC</start>
    <status>CONFIRMED</status>
    <summary>WinterWar 38</summary>
    <wholedauyevent>true</wholedauyevent>
</event>

Мы не будем забирать все поля, а заберем лишь summary, description, start datetime, end datetime и location. Сделать это очень просто, сначала мы заходим в блок event, создаем объект для наших данных, далее проходим в блоки полей, парсим данные и кладем из в поля нашего объекта. После чего сохраняем объект.

---
config:
    agent: Firefox
do:
- walk:
    to: https://www.google.com/calendar/ical/lirleni%40gmail.com/public/basic.ics
    do:
    - find:
        path: event
        do:
        - object_new: event
        - find:
            path: summary
            do:
            - parse
            - normalize:
                routine: replace_substring
                args:
                    \\: ''
            - object_field_set:
                object: event
                field: summary
        - find:
            path: description
            do:
            - parse
            - normalize:
                routine: replace_substring
                args:
                    \\: ''
            - object_field_set:
                object: event
                field: description
        - find:
            path: location
            do:
            - parse
            - normalize:
                routine: replace_substring
                args:
                    \\: ''
            - object_field_set:
                object: event
                field: location
        - find:
            path: start
            do:
            - parse:
                filter: (\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})
            - object_field_set:
                object: event
                field: start_date
        - find:
            path: end
            do:
            - parse:
                filter: (\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})
            - object_field_set:
                object: event
                field: end_date
        - object_save:
                name: event

Давайте запишем наш готовый конфиг в диггер и запустим его. Когда он закончит работу, перейдем в раздел с данными и удостоверимся, что они в полном порядке. Там вы увидите нечто похожее на:

Item #1 
start_date  2011-01-28 00:00:00
summary WinterWar 38
description Gaming Convention
end_date    2011-01-31 00:00:00
location    Champaign IL (USA)
Item #2 
start_date  2011-08-04 00:00:00
summary GenCon
description Gaming convention
end_date    2011-08-08 00:00:00
location    Indianapolis IN
Item #3 
start_date  2011-03-11 00:00:00
summary Madicon 20
description Science Fiction, with a large proportion of Gaming
end_date    2011-03-14 00:00:00
location    Harrisonburg VA, USA

Теперь переведем наш диггер в режим Active чтобы мы смогли скачать данные (пока диггер находится в режиме Debug, вы не можете скачивать данные, только просматривать выборку данных). Снова запустим его, дождемся окончания выполнения, перейдем в раздел с данными и скачаем их в нужном нам формате. Также вы можетес качать и изучить пример в формате XLSX.

Как вы видите, парсить данные с iCal ресурсов используя возможности Diggernaut очень просто!

Михаил Сисин: Со-основатель облачного сервиса по сбору информации и парсингу сайтов Diggernaut. Работает в области сбора и анализа данных, а также разработки систем искусственного интеллекта и машинного обучения  более десяти лет.
Related Post

This website uses cookies.