Пока пишется и дорабатывается новая версия «Блевантона«, рассмотрим один из вопрос, который довольно часто не дает спокойно спать начинающим программистам — работу с элементами веб-форм — SELECT (списки выбора).
Я не случайно перехожу сразу к такому сложному, на первый взгляд вопросу, опуская более простые, например заполнение текстовых полей. Тем, кто хочет разобраться в основах заполнения веб-форм я настоятельно рекомендую ознакомиться с постами Марии, автора блога «Парсинг и Я». Признаюсь честно — лучше я бы объяснить не смог :). В качестве практической части Мария разработала небольшую утилиту по регистрации RSS-каналов блога в различных RSS-каталогах. Вполне возможно, что кто-то захочет, используя её и мой опыт написать более универсальную и функциональную программу. А для того, чтобы Ваша программа в чем-то превосходила своих конкурентов — мы и рассмотрим вопрос по работе со списками SELECT.
На самом деле, работа с этими элементами практически не отличается от работы с теми же полями ввода. Давайте посмотрим, как выглядит список SELECT изнутри:
Крымские новости Памятники Крыма Новости рынка недвижимости
Вот пример списка с четырьмя возможными вариантами выбора один из которых — пустая строка. Судя по коду, для того, чтобы выбрать необходимый элемент на форме нам необходимо знать:
- Имя списка (атрибут name у тега select)
- Текст внутри тега option
Если изобразить графически список SELECT с двумя строками выбора, то получается примерно следующая картинка:
Зелеными флажками на рисунке отмечены данные, которые нам необходимо знать, чтобы однозначно выбирать тот или иной элемент списка.
Красным обозначены атрибуты, которые можно не рассматривать, но, в зависимости от фантазии программистов, пишущих каталоги, и эти атрибуты могут быть кое-где задействованы (был у меня однажды такой опыт при работе с каталогами сайтов).
Со свойством innerText я Вас уже знакомил на протяжении двух статей. Так что, остается разобрать на части наш SELECT. Сразу прикинем алгоритм работы.
Во-первых, необходимо найти на форме необходимый список.
Во-вторых, определить все видимые строки в этом списке.
В третьих, определить элемент списка, необходимый именно нам, например, это будет название категории в которую мы хотим добавить нашу RSS-ленту.
В-четвертых, нам необходимо выделить этот элемент на странице.
Пойдем по порядку, не забывая, что в мире есть такое понятие как DOM.
1. Объявляем переменные
Объявим три переменные:
var DocS : IHTMLElementCollection; Element: IHTMLElement; Options: IHTMLSelectElement;
DocS — коллекция однотипных элементов на странице;
Element — здесь будем хранить один из элементов коллекции;
Options — а это необходимый нам список.
Как видите, в нашем распоряжении появляется ещё один интерфейс IHTMLSelectElement, который и предоставляет нам методы работы со списками.
2. Ищем список для выбора категории
Поиск необходимого списка SELECT можно организовать вот в таком простеньком цикле:
... DocS:=(WebBrowser1.Document as IHTMLDocument2).all.tags('select') as IHTMLElementCollection; for I:=0 to Docs.length-1 do begin Element:=DocS.item(i,0)as IHTMLElement; if Element.getAttribute('name',0)='rss_cat' then begin ShowMessage('Элемент формы найден'); Options:=(Element as IHTMLSelectElement); end; ...
То есть, здесь мы поочередно перебрали все элементы SELECT на странице и определили необходимый нам список с помощью его атрибута name. После чего присвоили значение Element переменной Options.
3. Определяем необходимый элемент списка и выделяем его
Здесь опять же воспользуемся циклом по всем элементам OPTION найденного списка:
for j:= 0 to Options.length-1 do begin if (Options.item(j,0)as IHTMLElement).innerText='Памятники Крыма' then Options.selectedIndex:=j; end;
Как видите, в данном случае я проводил поиск с целью найти элемент списка, содержащего точную фразу «Памятники Крыма». С небольшим изменением этот же цикл можно приучить выискивать неточные совпадения или сравнивать каждый элемент списка с целым перечнем Ваших категорий.
Кстати, для неточного сравнения строк можно использовать наивный алгоритм.
4. Резюме
Итак, для того, чтобы получить доступ ко всем элементам списка необходимо использовать в работе интерфейс IHTMLSelectElement, предоставляющий доступ к методам работы со списками. Причем, для работы с этим интерфейсом не обязательно использовать промежуточный переход от IHTMLElemet к IHTMLSelectElement, как это делал я. Я просто показал по шагам как добраться до списка. Более рациональным вариантом цикла поиска и выделения необходимого элемента списка будет следующий:
DocS:=(WebBrowser1.Document as IHTMLDocument2).all.tags('select') as IHTMLElementCollection; for I:=0 to Docs.length-1 do begin Element:=DocS.item(i,0)as IHTMLSelectElement; if Element.name='rss_cat' then begin ShowMessage('Элемент формы найден'); for j:= 0 to Element.length-1 do begin if (Element.item(j,0)as IHTMLElement).innerText='Памятники крыма' then Element.selectedIndex:=j; end; end; end;
Здесь я не использую лишних интерфейсов и сразу работаю со списком. Ведь я ясно указал в начале, что мне необходима коллекция всех SELECT со страницы. Вот так запросто Вы можете написать программу для регистрации в каталогах и при этом программа сама найдет и выделит необходимую категорию.
По «странному стечению обстоятельств» у меня в заготовках для публикации на блоге тоже уже написана статья про работу с селектами)) Хотя — ничего странного, у нас же тематики пересекаются)
Но подходы к решению задачи у нас разные? Я обычно все что касается парсинга читал :)