Categories

A sample text widget

Etiam pulvinar consectetur dolor sed malesuada. Ut convallis euismod dolor nec pretium. Nunc ut tristique massa.

Nam sodales mi vitae dolor ullamcorper et vulputate enim accumsan. Morbi orci magna, tincidunt vitae molestie nec, molestie at mi. Nulla nulla lorem, suscipit in posuere in, interdum non magna.

Парсинг html-страницы с помощью XPath в R

В связи с идеей провести лёгкий анализ ответов кандидатов в Координационный совет оппозиции на вопросы “Политического компаса” возникла необходимость пропарсить полученный html-файл и вытащить из него имена кандидатов и их ответы. Я уже раньше сталкивался с подобной задачей и поэтому решил работать с файлом не как с текстом, который обрабатывается регулярными выражениями, а как с html-документом, который обрабатывается специальными для этого случая инструментами.

В R-расширении XML есть функция htmlTreeParse, которая преобразует html-файл в объект, который далее можно “разбирать” на кусочки средствами R.

1
2
library(XML)
doc <- htmlTreeParse('data/compass.cvk2012.org.htm', useInternalNodes = T)

Теперь нам надо понять, в каких элементах html-дерева хранятся нужные нам данные. Самый прогрессивный, по некоторым источникам, способ работы с деревом – это XPath, язык запросов к элементам XML-документа. Для того, чтобы быстрее понять структуру интересующего html-документа и построить необходимый XPath-запрос, воспользуемся браузером Firefox с расширениями firebug и firePath. Более подробно об этом можно почитать, например, в публикации “Примеры xpath-запросов к html“.

Данные об ответах кандидатов на вопросы компаса хранятся в тэге div класса candidate_compass_data. Для отбора этих тэгов воспользуемся следующей командой:

3
candidcompass <- getNodeSet(doc, "//div[@class='candidate_compass_data']")

Здесь getNodeSet – это команда из пакета XML, которая в нашем случае отбирает из документа doc узлы, которые соответствуют запросу “//div[@class='candidate_compass_data']“. Результатом работы функции является список (list), в каждом из элементов которого хранится очередной тэг, соответствующий XPath-запросу.

Далее вытягиваем значение, хранящееся в тэге:

4
5
library(plyr)
compass <- laply(candidcompass, xmlValue)

Здесь laply – функция из пакета plyr, которая на входе получает список (первая буква L в названии функции – сокращение от list) candidcompass, далее применяет к каждому элементу списка функцию xmlValue (о ней чуть позже), а результаты возвращает в виде массива (вторая буква в названии функции A – от array).

Функция xmlValue из пакета XML возвращает значение XML(HTML)-тэга.

Теперь в переменной compass у нас хранятся текстовые строки вида “[2,-1,-1,1,2,1,-1,2,-1,0,2,1,1,-2,-1,2,-2,0,-2,2,-2,0,2,2,2]”. Нам нужно преобразовать их в числовой массив. Для начала удалим квадратные скобки по бокам. Для этого воспользуемся функцией str_replace пакета stringr, которая производит в строке замену по регулярному выражению.

6
7
library(stringr)
compass <- str_replace(compass, '\\[(.*)\\]', '\\1')

Теперь compass стал напоминать файл со значениями, разделёнными запятыми. Чем и воспользуемся:

8
compass <- read.table(textConnection(compass), sep=',')

В итоге, переменная compass содержит массив с ответами кандидатов. Сделаем более содержательные заголовки переменных:

9
10
varlabs <- c("Парл.респуб", "Защит.пошлины", "Огранич.миграц.", "Госучр.из Мск", "Оппозиц.на выборы", "Беспл.мед. и обр", "ЭксСССР", "Бюдж.в рег", "Проф.армия", "Плоск.налог", "Интегр.с ЕС", "Оружие", "ЕГЭ", "Тит.нация", "Нет ЕР", "Выборн.МСУ", "Деньги Кавказу", "Пересм.приватиз", "Госкорпорац", "Накопит.пенс", "Религ.в УК", "Альтер.парлам", "Присяжн.УК", "Либерал.экон", "Компромисс с власт")
names(candidates)[2:26] <- varlabs

Аналогичным образом получаются имена кандидатов. Полный исходный код скрипта доступен в моём аккаунте на GitHub.

1 comment to Парсинг html-страницы с помощью XPath в R

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>