Я пытаюсь сгенерировать селекторы CSS для случайных элементов на веб-странице с помощью C #. Немного предыстории:
Я использую форму с элементом управления WebBrowser. Во время навигации можно запросить селектор CSS для элемента под курсором. Получение html-элемента, конечно, тривиально, с помощью:
WebBrowser.Document.GetElementFromPoint();
Цель состоит в том, чтобы создать «строгий» селектор CSS, ведущий к элементу под курсором, а-ля:
html > body > span:eq(2) > li:eq(5) > div > div:eq(3) > span > a
Этот селектор основан на :eq, поскольку они предназначены для обработки с помощью jQuery и / или SizzleJS (эти два поддерживают: eq - оригинальные селекторы CSS не поддерживают. Поднимите вверх @BoltClock за помощь в разъяснении этого вопроса). Итак, вы поняли. Для достижения этой цели мы передаем извлеченный элемент HtmlElement указанному ниже методу и начинаем подниматься вверх по дереву DOM, запрашивая родительский элемент для каждого элемента, с которым мы сталкиваемся:
private static List GetStrictCssForHtmlElement(HtmlElement element)
{
List familyTree;
for (familyTree = new List(); element != null; element = element.Parent)
{
string ordinalString = CalculateOrdinalPositionAmongSameTagSimblings(element);
if (ordinalString == null) return null;
familyTree.Add(element.TagName.ToLower() + ordinalString);
}
familyTree.Reverse();
return familyTree;
}
private static string CalculateOrdinalPositionAmongSameTagSimblings(HtmlElement element, bool simplifyEq0 = true)
{
int count = 0;
int positionAmongSameTagSimblings = -1;
if (element.Parent != null)
{
foreach (HtmlElement child in element.Parent.Children)
{
if (element.TagName.ToLower() == child.TagName.ToLower())
{
count++;
if (element == child)
{
positionAmongSameTagSimblings = count - 1;
}
}
}
if (positionAmongSameTagSimblings == -1) return null; // Couldn't find child in parent's offsprings!?
}
return ((count > 1) ? (":eq(" + positionAmongSameTagSimblings + ")") : ((simplifyEq0) ? ("") : (":eq(0)")));
}
Этот метод надежно работал для множества страниц. Однако есть одна конкретная страница, которая заставляет меня задуматься:
http://www.delicious.com/recent
Попытка получить селектор CSS любого элемента в списке (в центре страницы) не удалась по одной очень простой причине:
После того, как вознесение попадает в первый элемент SPAN на своем пути вверх (вы можете обнаружить его, проверив страницу с помощью инструментов веб-разработки IE9 для проверки), он пытается обработать его, вычисляя его порядковый номер среди это же братья и сестры тегов. Для этого нам нужно запросить родительский узел для братьев и сестер. Здесь все становится странно. Элемент SPAN сообщает, что его родительский элемент является элементом DIV с id = "latest-index". Однако это не непосредственный родительский элемент SPAN (непосредственным родителем является LI class = "wrap isAdv"). Это приводит к сбою метода, потому что - что неудивительно - он не может определить SPAN среди детей.
Но это становится еще более странным. Я получил и изолировал HtmlElement самого SPAN. Затем я получил его Parent и использовал его для повторного спуска обратно к элементу SPAN, используя:
HtmlElement regetSpanElement = spanElement.Parent.Children[0].Children[1].Children[1].Children[0].Children[2].Children[0];
Это привело нас обратно к узлу SPAN, который мы начали ... с одним поворотом:
regetSpanElement.Parent.TagName;
Теперь он сообщает LI как родитель XX. Как это может быть? Есть идеи?
Еще раз спасибо заранее.
Примечания:
Я сохранил код Html (в том виде, в котором он представлен внутри WebBrowser.Document.Html) и сам проверил его, чтобы быть на 100% уверенным, что ничего забавного не происходит place (иначе говоря, для элемента управления WebBrowser используется другой код, чем тот, который я вижу в IE9, но этого не происходит, структура соответствует 100% для указанного пути).
Я запускаю элемент управления WebBrowser в режиме IE9, используя инструкции, изложенные здесь:
http://www.west-wind.com/weblog/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version
Попытка запустить управление WebBrowser и IE9 настолько же, насколько это возможно.
Я подозреваю, что наблюдаемые эффекты могли быть вызваны каким-то скриптом, запущенным за моей спиной. Однако мои познания в области веб-программирования не так уж велики, чтобы определить его.
Изменить: Опечатки