пятница, 5 апреля 2013 г.

Node.js: парсинг HTML, XML с помощью xpath

Внеочередной пост из разряда "Для начинающих". Пост прежде всего написан для того чтобы, показать базовые принципы работы с xpath в node.js, а так же как одна из вариаций "Hello, world!" с использованием node.js.
Стоит отметить, что я никогда не писал  ничего серьезного на JavaScript, и Node.js в частности,  поэтому  приветствуются любые поправки и улучшения.
Я не буду писать вступление о том, что такое Node.js, так как информации об этом предостаточно.

В качестве практической задачи рассмотрим парсинг страницы приложения в Apple App Store. Например, вот эту.
Начинать любой, даже простой скрипт на Node.js лучше с package.json. Назначение этого файла достаточно простое - в нем мы описываем базовую информацию разрабатываемого проекта (модуля), будь то автор, версия, зависимости. Я не случайно отметил возможность описания зависимостей, так как именно это позволяет сделать скрипт переносимым. Файл можно  создать как самому, так и с помощью node package manager (npm), используя следующую npm init.
Например, так выглядит package.json используемый в разработанном модуле:
{
    "name": "appstore-parser",
    "author": "Vasily Fomin",
    "version": "0.0.1",
    "private": true,
    "dependencies": {
        "xpath": "latest",
        "xmldom" : "latest",
        "request" : "latest"
    }
}
Для того чтобы окончательно понять как устроен данный файл, и какие возможности он предоставляет советую посмотреть на интерактивную справку.
Когда package.json заполнен, необходимые зависимости устанавливаются с помощью команды
npm i, сокращение от npm install. Которая, в отличие от команды npm install package_name
устанавливает их на проектной основе, а не на системном уровне.

Благодаря динамичности языка, сам парсинг осуществляется очень просто, и наибольшую сложность составляет написание правильного xpath запроса. Ниже представлен полный код получившегося парсера:
А также пример использования:
var parser = require('./appstore-parser');
parser.loadWithCallBack('https://itunes.apple.com/us/app/sonic-dash/id582654048?mt=8', function (data) {
    for (var prop in data) {
        console.log(prop + ": " + data[prop]);
    }
});

Печать всех доступных, на данный момент, свойств:
title: Sonic Dash
developer: By SEGA
description: Sonic Dash is now free. Thanks to everyone who has downloaded the game. Look out for more free rewards coming soon!
logo: http://a4.mzstatic.com/us/r1000/103/Purple2/v4/82/0b/a6/820ba6b8-b39e-4aa3-466a-a874354208c7/mzl.oubnjrnp.175x175-75.jpg
price: Free
genre: Games
releasedate: Mar 29, 2013
requirements: Compatible with iPhone 3GS, iPhone 4, iPhone 4S, iPhone 5, iPod touch (3rd generation), iPod touch (4th generation), iPod touch (5th generation) and iPad. Requires iOS 5.0 or later. This app is optimized for iPhone 5.
language: English
copyright: ©SEGA. SEGA, the SEGA logo, SONIC THE HEDGEHOG and Sonic Jump are either registered trade marks or trade marks of SEGA Corporation. All rights reserved.
apprating: Rated 4+
currentversion: 4960 Ratings
currentversionstar: 3 and a half stars
allversions: 3239 Ratings
allversionsstar: 3 and a half stars
iphonescreenshots: http://a1142.phobos.apple.com/us/r1000/097/Purple2/v4/ed/ce/5e/edce5e7c-2339-0918-bedb-549280d6b3be/mzl.pplwqwrz.320x480-75.jpg,http://a935.phobos.apple.com/us/r1000/106/Purple2/v4/77/9c/97/779c973a-1c3e-ca00-e929-a6fc79e3846c/mzl.eqftsqin.320x480-75.jpg,http://a1543.phobos.apple.com/us/r1000/113/Purple2/v4/b6/8c/9d/b68c9d22-3fb8-93af-2ab8-724cfc7a3e1b/mzl.pbtwhfly.320x480-75.jpg,http://a1068.phobos.apple.com/us/r1000/078/Purple2/v4/de/61/b8/de61b8b4-f836-d581-1cd4-941c4312db4d/mzl.ipyubrmb.320x480-75.jpg,http://a1269.phobos.apple.com/us/r1000/104/Purple2/v4/cc/5c/5e/cc5c5efc-130a-13c2-b55c-3c454c3c6f24/mzl.tptxvnpu.320x480-75.jpg
ipadscreenshots: http://a248.phobos.apple.com/us/r1000/062/Purple2/v4/45/90/b9/4590b9c6-32a2-718f-660a-31939daf2c0d/mzl.viobxkvb.480x480-75.jpg,http://a1412.phobos.apple.com/us/r1000/098/Purple2/v4/5b/46/50/5b465072-43c9-628d-1fe7-21ce56c48b00/mzl.visuxmml.480x480-75.jpg,http://a1656.phobos.apple.com/us/r1000/073/Purple/v4/fa/d7/98/fad7983f-905e-be33-0e35-35893ec43730/mzl.phldzqfj.480x480-75.jpg,http://a1117.phobos.apple.com/us/r1000/079/Purple2/v4/44/38/a0/4438a0df-b6f9-806b-1590-4e54d464843a/mzl.ohvalbzk.480x480-75.jpg,http://a388.phobos.apple.com/us/r1000/085/Purple2/v4/7c/e4/e7/7ce4e768-eaca-8b93-489d-a65a93f6162e/mzl.exqicyhx.480x480-75.jpg

Алгоритм работы следующий: с помощью модуля request посылается запрос к серверу на получение страницы, в случае успешного запроса, по функции обратного вызова полученные данные передается в функцию parse, где из полученных данных строится дом дерево с помощью xmldom, и осуществляется выборка данных с помощью xpath, которые складываются в объект data. Хорошей практикой считается прогонка полученных "сырых" данных через библиотеку HTML Tidy, которая приводит их к соответствующему стандарту HTML тем самым, позволяя избежать ошибок при построении DOM дерева. На текущий момент у меня есть некоторые проблемы с использованием данного модуля, поэтому код вызова соответствующих методов не включен.

Немного о написании xpath. xpath представляет собой язык запросов для получения адреса элемента или элементов в DOM дереве, а также позволяет выполнять некоторые вычисления.
Например,
//div[@id="title"]
позволяет получить все div элементы дерева с id равным "title".

Отличным помощником в написании xpath для HTML документа являются Google Chrome Developer Tools, или их аналоги в других браузерах, например, Firebug в Firefox. Открыв вкладку "Console" мы получаем в наше распоряжение объект $x через который можно писать xpath запросы для текущего документа, и получать соответствующие объекты дерева в реальном времени, например:
Отладка XPath в GoogleChrome Deveveloper Tools
На этом все. Код примеров на Github.

Комментариев нет:

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