|
ЭлементБлокHTML Как получить дочерние узлы подчинённые только текущему элементу? | ☑ | ||
---|---|---|---|---|
0
artist
03.06.14
✎
17:46
|
Делаю парсинг сайта, код примерно такой:
ЧтениеHTML = Новый ЧтениеHTML; ЧтениеHTML.ОткрытьФайл(Адрес, "windows-1251"); ПостроительDOM = Новый ПостроительDOM; ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML); Дивы = ДокументHTML.ПолучитьЭлементыПоИмени("div"); Для Каждого ТекДив Из Дивы Цикл АйдишникДива = ТекДив.Атрибуты.ПолучитьИменованныйЭлемент("id");//ПолучитьЭлементПоИдентификатору не захотел работать, говорит id не является идентификатором Если АйдишникДива <> Неопределено Тогда Если АйдишникДива.Значение = "p_list" Тогда Строки = ТекДив.ПолучитьЭлементыПоИмени("tr"); Для Каждого ТекСтрока ИЗ Строки Цикл //тут хочу выбрать подчинённые строке (tr) элементы (td), причём подчинённые ТОЛЬКО текущей строке, но не вложенным таблицам //а выбирает все ячейки (td), включая вложенные таблицы //делаю так: Ячейки = ТекСтрока.ДочерниеУзлы; //пробовал так: //Ячейки = ТекСтрока.ПолучитьЭлементыПоИмени("td"); - тоже фигня получается (выбирает все td'шки, включая вложенные таблицы) КонецЦикла; КонецЕсли; КонецЕсли; КонецЦикла; Пример кода сайта, который соответствует ТекСтрока: <tr bgcolor="#FFEEAA"> <td width="100"> <a href="ССЫЛКА НА ТОВАР"> <img class="short_img" src="какая-то картинка..."> </a> </td> <td width="350"> <a class="short_style" href="ССЫЛКА НА ТОВАР"> <span>НАЗВАНИЕ ТОВАРА</span> </a> </td> <td> <table width="100%" border="0" style="border-collapse: collapse"> <tbody> <tr valign="centr"> <td width="10" bgcolor="#FFEEAA"></td> <td width="150" bgcolor="#3333FF" align="center"> <font face="Impact">склад Москва</font> </td> <td width="50" bgcolor="#00923F" align="center"> <font face="Impact"> <i>Есть</i> </font> </td> <td width="85" bgcolor="#FFFFFF" align="center"> <font face="Impact">9390 руб.</font> </td> <td width="70" bgcolor="#FFFF00" align="center"> <p>КУПИТЬ</p> </td> <td width="10" bgcolor="#FFEEAA"></td> </tr> <tr> <td class="small" align="right" heigth="2" colspan="5">в наличии - 4</td> </tr> </tbody> </table> </td> </tr> Собственно вопрос, как получить только элементы подчинённые ТекСтрока (т.е. только ячейки текущей таблицы)? Или может ПостроительDOM не лучший вариант? Что сейчас кошерно использовать для парсинга сайтов? Ещё на всякий случай, сейчас: ТекСтрока.ДочерниеУзлы.Количество() = 11 А мне нужно что бы было = 3 ЗЫ 8.2.18.109 , но это не принципиально, могу и последнюю 8.3 использовать... ЗЗЫ Обычные формы. |
|||
1
Котокот
03.06.14
✎
18:01
|
(0) АйдишникДива = ТекДив.Атрибуты.ПолучитьИменованныйЭлемент("id"); - это неправильно, поэтому и не работает
|
|||
2
artist
03.06.14
✎
18:04
|
(1)В чём неправильность?
Данный код получает атрибут тэга, в частности id, дальше значение этого атрибута я сравниваю с нужным: Если АйдишникДива.Значение = "p_list" Тогда .... И только этот див (ТекДив) обрабатываю... Пробовал сделать так: ДокументHTML.ПолучитьЭлементПоИдентификатору("p_list") - ничего не находит... |
|||
3
Поpyчик-4
03.06.14
✎
21:10
|
(0) Я парсил некий сайт с упорото блочной cтруктурой HTML, построенной на div и как ни странно, алгоритм близко похожий на мой. Использовал ПостроительDOM, вся работа заняла примерно два рабочих дня чистого времени. Большая часть ушла на восстановление подзабытых знаний.
зы перед парсингом страницы, я предварительно программно вычищал из неё ненужное, потом приводил имена классов css к идентификаторам, чтобы потом использовать соответствующие методы. Кусок из обработки СтрокаHTML = СтрЗаменить(СтрокаHTML, "<div class=""b-catalog-table"">", "<div class=""b-catalog-table"" id=""b-catalog-table"">"); СтрокаHTML = СтрЗаменить(СтрокаHTML, "<div class=""catalog-before-ads"">", "<div class=""catalog-before-ads"" id=""catalog-before-ads"">"); СтрокаHTML = СтрЗаменить(СтрокаHTML, "<div class=""catalog-after-ads"">", "<div class=""catalog-after-ads"" id=""catalog-after-ads"">"); СтрокаHTML = СтрЗаменить(СтрокаHTML, " ", " "); ЧтениеHTML = Новый ЧтениеHTML; ЧтениеHTML.УстановитьСтроку(СтрокаHTML); ПостроительDOM = Новый ПостроительDOM; ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML); БлокОбъявлений = ДокументHTML.ПолучитьЭлементПоИдентификатору("b-catalog-table"); Если НЕ БлокОбъявлений.ЕстьДочерниеУзлы() Тогда Возврат; КонецЕсли; |
|||
4
artist
04.06.14
✎
09:56
|
(3)Ну да... Смысл тот же... Спасибо на добром слове...
Я со своей проблемой практически разобрался... У меня не .ДочерниеУзлы выдавало лишние элементы, а ТекДив.ПолучитьЭлементыПоИмени("tr") Похоже этот оператор получает все теги с указанным именем ниже текущего элемента, включая вложенные таблицы... Переделал этот код на ТекДив.ДочерниеУзлы[1].ДочерниеУзлы[0].ДочерниеУзлы теперь всё работает. Понимаю что коряво, но похоже сайт на более-менее нормальном движке, и на каждой странице такая закономерность прослеживается, так что пока пойдёт... Теперь у меня другая проблемка нарисовалась. На сайте некоторые страницы подгружаются при скролле до конца страницы (при помощи JavaScript'a). Я это обошёл - добавил на форму ПолеHTMLДокумента, гружу нужную страницу в него, при помощи ЭлементыФормы.Сайт.Перейти(НужнаяСсылка); Добавил программный скроллинг, и после последнего скроллинга (после подгрузкий всей страницы) по таймауту в несколько секунд вызываю процедуру парсинга загруженной страницы. Получаю код HTML с ПоляHTML при помощи HTMLТекст = ЭлементыФормы.Сайт.ПолучитьТекст(); Но! Оказывается, что текст содержит только первую версию сайта (без динамически подгруженных данных). Почему такое может быть? Как получить HTML код того, что в данный момент отображается в ПолеHTMLДокумента на форме? |
|||
5
artist
04.06.14
✎
09:59
|
ЗЫ Процедуру парсинга вызываю не напрямую - типа ПарсингСтраницы() а через ПодключитьОбработчикОжидания("ПарсингСтраницы",5,Истина);
Т.е. за 5 секунд страница точно вся загружена, и только после этого я начинаю анализировать код страницы... Можно ли как-то из COMОбъекта (ЭлементыФормы.Сайт.Документ) получить полный текст страницы? Возможно там есть обновлённые данные... |
|||
6
artist
04.06.14
✎
10:06
|
Догадка подтвердилась, COMОбъект содержит все данные... надо как-то вытянуть из него HTML код...
|
|||
7
Котокот
04.06.14
✎
10:11
|
(2) Да, наверное это я затупил, прошу прощения
|
|||
8
Котокот
04.06.14
✎
10:11
|
(6) А зачем COMОбъект, DOM со всем этим вполне справляется.
|
|||
9
artist
04.06.14
✎
10:30
|
(8)Насколько я понимаю:
что бы получить DOM-объект - надо откуда-то взять HTML-код - либо загрузить с определённой страницы сайта, либо открыть из файла, либо задать явной строкой из памяти. Или у ПолеHTMLДокумента есть прямой доступ к DOM-модели? Посмотрел в СП, нашёл только это: ПолеHTMLДокумента (HTMLDocumentField) Свойства: Вывод (Output) Документ (Document) Рамка (Border) ЦветРамки (BorderColor) В свою очередь Документ имеет свойство COMОбъект, свойства и методы которого описаны тут: http://msdn.microsoft.com/en-us/library/ms531073(VS.85).aspx Но что-то я не нашёл там возможности получить исходный код страницы... Как-то это странно. |
|||
10
artist
04.06.14
✎
10:32
|
+(9) Сейчас, что бы получить DOM я делаю так:
ЧтениеHTML = Новый ЧтениеHTML; ЧтениеHTML.УстановитьСтроку(ЭлементыФормы.Сайт.ПолучитьТекст()); ПостроительDOM = Новый ПостроительDOM; ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML); ...ну и дальше пошёл стандартный перебор как в постах выше... Где ЭлементыФормы.Сайт = ПолеHTMLДокумента... И вот в этом месте текст содержит не все загруженные данные, в отличии от COMОбъекта... Есть ли какой-нибудь другой способ получить DOM или текст отображаемого сайта? |
|||
11
Котокот
04.06.14
✎
10:34
|
(10) Так дождаться загрузки страницы. У поля HTML есть же метод ПриЗагрузке(), или как он там точно называется.
|
|||
12
artist
04.06.14
✎
10:38
|
(11)Так дождался...
У поля HTML есть событие ДокументСформирован() Проблема в том, что это событие вызывается только один раз, при первой полной загрузке страницы. При динамической подгрузке содержимого страницы (полагаю что на сайте используется JavaScript+ajax) это событие не срабатывает... |
|||
13
artist
04.06.14
✎
10:42
|
+(12) Но я обошёл это таким образом:
Процедура Сайтonpropertychange(Элемент, pEvtObj) ПодключитьОбработчикОжидания("СкролВниз",0.2,Истина); ОтключитьОбработчикОжидания("ПарсингТоваров"); Если ТекущаяСтрокаГруппы <> Неопределено Тогда ПодключитьОбработчикОжидания("ПарсингТоваров",5,Истина); КонецЕсли; КонецПроцедуры т.е. по событию onpropertychange подключаю скроллинг, и в конце ставлю таймаут на процедуру ПарсингТоваров. Т.е. Процедура ПарсингТоваров вызовется через 5 секунд после последней итерации подгрузки страницы... Но, видимо 1Сный объект не обновляет свои данные после того, как страница была полностью сформирована... В отличии от COMОБъекта, который содержит все текущие данные отображаемые в поле... |
|||
14
artist
04.06.14
✎
11:23
|
Апну с надеждой...
|
|||
15
artist
04.06.14
✎
16:27
|
Если кому будет интересно - можно получить текст через ком при помощи
ЭлементыФормы.ПолеХТМЛ.Документ.body.innerHTML или ЭлементыФормы.ПолеХТМЛ.Документ.body.outerHTML |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |