Главная » Silverlight » Извлечение данных из HTML-кода

0

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

ненадежный способ, потому что при его исполь­зовании код приложения зависит от структуры HTML-страницы. После изменения структуры страницы код приложения становится нерабо­тоспособным. Однако в некоторых случаях непо­средственное извлечение — единственный спо­соб получения данных. В прошлом, до появления служб Amazon и eBay, разработчики приложений часто использовали непосредственное извлечение для получения информации о ценах, изображений продуктов и т.д.

Далее рассматривается пример извлечения дан­ных из таблицы HTML, показанной на рис. 20.2. В таблице приведено население Земли в разные годы (сокращение "ВСЕ" означает "до нашей эры"; в таблице применен американский формат чисел).

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

<table> <tr> <th>rofl</th>

<th width=" 7 0 ">KojiH4ecTBo</th> </tr> <tr>

<th>70,000 BCE</th> <td>2</td> </tr> <tr>

<th>10,000 BCE</th> <td>l,000</td> </tr> <tr>

<th>9000 BCE</th> <td>3,000</td> </tr>

</table>

Класс WebClient предоставляет возможность загрузить документ HTML. После этого необходимо извлечь данные из разметки документа.

В главе 6 рассматривается использование метода WebClient. OpenReadAsync () для загрузки файла как потока байтов. Полученный поток можно читать с помощью объекта StreamReader (для текстовых данных) или BinaryReader (для двоичных дан­ных). Небольшие объемы текстового содержимого можно читать с помощью метода WebClient. DownloadStringAsync (), возвращающего строку. В данном примере исполь­зуется метод DownloadStringAsync о .

На рис. 20.3 показано приложение Silverlight, позволяющее извлекать информацию из таблицы HTML, показанной на рис. 20.2. Пользователь вводит год. Код приложе­ния ищет на странице соответствующую ячейку, а затем извлекает число из смежного столбца. Значения не интерполируются. Это означает, что если заданный пользовате­лем год не совпадает с приведенным в таблице, результат не возвращается.

Когда пользователь щелкает на кнопке Извлечь данные, код приложения создает объект WebClient и вызывает метод DownloadStringAsync (), предо­ставив ему соответствующий адрес сайта.

private void cmdGetData_Click(object sender,

RoutedEventArgs e)

{

WebClient client = new WebClient();

Uri address = new Uri("http://localhost:" + HtmlPage.Document.DocumentUri.Port + "/ASPWebSite/PopulationTable.html");

client.DownloadStringCompleted += client_DownloadStringCompleted;

client.DownloadStringAsync(address);

)

Совет. При запуске асинхронной операции рекомендуется обновить пользовательский интерфейс, добавив сообщение О статусе операции. Например, можно вывести объект TextBlock С текстом Ожидается результат запроса веб-службы.

Ниже приведен код, получающий результаты запроса.

private void client_DownloadStringCompleted(object sender,

DownloadStringCompletedEventArgs e)

{ ‘

string pageHtml = "";

try

{

pageHtml = e.Result;

)

catch

(

lblResult.Text = "Запрос не выполнен.";

return;

)

Если запрос неуспешный (например, запрошенной страницы не существует или кроссдоменный доступ не разрешен), то при чтении свойства Result будет сгенериро­вано исключение. Поэтому необходим код обработки исключения.

Теперь необходимо извлечь информацию из строки HTML. Можно визуально просмо­треть строку, проверяя каждый символ, однако намного легче применить регулярное выражение. Язык регулярных выражений часто используется для поиска текста или проверки вводимых данных. С помощью методов класса String в строке можно най­ти заданную последовательность символов (например, слово hello), однако регулярные выражения более гибкие. Например, с их помощью можно найти любое слово, состоя­щее из пяти букв и начинающееся с бутсвы h. Регулярные выражения рассматриваются в главе 17, в которой они применяются для проверки объектов данных.

В рассматриваемом примере необходимо найти фрагменты разметки HTML в сле­дующей форме.

Рис. 20.3. Запрос страницы HTML с помощью класса WebClient

<th>500 BCE</thxtd>100,000</td>

ГЬд, размещенный в элементе <th>, является ключевым значением, задаваемым пользователем, а число, расположенное в элементе <td>, — результирующим значени­ем, которое необходимо извлечь.

Существует несколько способов создания регулярного выражения, извлекающего результат. Наиболее простой и чистый способ основан на использовании именованных групп. Именованная группа — это заполнитель, представляющий информацию, кото­рую нужно извлечь. Разработчик задает имя группы, а затем при необходимости извле­кает ее значение. Именованная группа имеет следующий синтаксис.

(?<имя_группы>регулярное_выражение)

Ниже приведен пример именованной группы.

(?<population>.*)

Эта группа имеет имя population. В ней используется регулярное выражение .*. Точка обозначает любой символ, кроме новой строки, а звездочка — произвольное (в том числе нулевое) количество вхождений образца. Символ произвольный, количество произвольное, следовательно, значением группы population может быть любая после­довательность символов.

Какая же в таком случае от нее польза? Именованная группа полезна, когда она включена в другое регулярное выражение. Например, приведенное ниже регулярное выражение извлекает содержимое элемента <td> за 1985 год.

<th>1985</th>\s*<td>(?<population>.*)</td>

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

<th>1985</th>

После элемента <th> может находиться произвольное, включая нулевое, количе­ство пробельных символов (пробелов, новых строк, жестких возвратов каретки и т.д.). Пробельные символы представлены метасимволом \s.

<th>1985</th>\s*

После метасимвола \s* расположено литеральное представление открывающего де­скриптора <td>, а затем — именованная группа, возвращающая искомое значение.

<th>1985</th>\s*<td>(?<population>.*)

И наконец, литерал </td> представляет закрывающий дескриптор столбца значений.

Регулярное выражение создается программно, поэтому год не обязательно должен быть жестко закодированным. Пользователь вводит значение года в текстовое поле tx- tYear. Введенное значение вставляется в строку регулярного выражения.

string pattern = "<th>" + txtYear.Text + "</th>" + @"\s*" + "<td>" + "(?<population>.*)" + "</td>";

Теперь нужно создать объект Regex, в котором используется регулярное выражение pattern, и передать строку, содержащую документ HTML, методу Regex.Match О . Имя группы используется для извлечения искомого значения.

Regex regex = new Regex(pattern);

Match match = regex.Match(pageHtml);

string people = match.Groups["population"].Value;

if (people == "")

lblResult.Text = "Год не найден."; else

lblResult.Text = match.Groups["population"].Value + " тысяч человек.";

}

Это не очень элегантный способ извлечения данных из страницы HTML. Пример лишь демонстрирует использование классов WebClient и Regex в качестве простых инструмен­тов извлечения данных из разметки HTML и других текстовых источников. Аналогичные регулярные выражения используются и в других службах, таких как REST (см. далее).

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

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