Логика для реализации динамического веб-скребка в C # - PullRequest
2 голосов
/ 23 января 2010

Я хочу разработать веб-скребок в формах окон C #. Я пытаюсь сделать следующее:

  1. Получить URL от пользователя.
  2. Загрузка веб-страницы в элементе управления IE UI (встроенный браузер) в WINForms.
  3. Разрешить Пользователю выбирать текст (непрерывный, маленький (не более 50 символов)). с загруженной веб-страницы.
  4. Когда пользователь желает сохранить местоположение ( местоположение HTML DOM ), его необходимо сохранить в БД, чтобы пользователь мог использовать это местоположение для извлечения данных из этого местоположения во время его последующей посещения.

Предположим, что загруженный веб-сайт является сайтом, включающим прайс-лист, и котируемая ставка постоянно меняется, идея состоит в том, чтобы сохранить иерархию DOM, чтобы в следующий раз я мог пересечь ее.

Я мог бы сделать это, если бы все элементы HTML имели свои атрибуты id. В случае, когда идентификатор равен нулю, я не могу этого сделать.

Может ли кто-нибудь предложить правильную идею по этому поводу (возможно, минимальный фрагмент кода)?

Было бы полезно, даже если вы можете поделиться некоторыми онлайн-ресурсами.

спасибо,

Виджей

Ответы [ 2 ]

2 голосов
/ 23 января 2010

Один из подходов - создать стек тегов / стилей / идентификаторов для элемента, который вы хотите выбрать.

От нужного элемента перейдите к ближайшему элементу id. Таким образом вы избавитесь от большей части верхнего заголовка и т. Д. Затем создайте последовательность для поиска.

Пример:

<html>
  <body>
    <!-- lots of html -->
    <div id="main">
       <div>
          <span>
             <div class="pricearea">
                <table> <!-- with price data -->

Например, вы должны хранить в своей БД последовательность: [id = main], div, span, div, table или, возможно, div [class = pricearea], таблица .

Использование стилей / классов также может быть использовано для создания вашего пути. Вы можете выбрать тег, атрибут тега или их комбинацию. Вы хотите, чтобы он был максимально точным с минимальным количеством элементов, чтобы сделать его более надежным.

Если раскладка редко изменяется, это позволит вам каждый раз перемещаться в одно и то же место.

Я бы также предложил вам использовать HTML Agility Pack или что-то подобное для анализа DOM, так как элемент управления IE медленный.

Соскоб с экрана - это весело, но сложно получить 100% для всех страниц. Удачи!

0 голосов
/ 09 февраля 2010

После небольшого поиска я наткнулся на довольно простое решение. Ниже прикреплен образец фрагмента.

if (webBrowser.Document != null)
        {
            IHTMLDocument2 HtmlDoc = (IHTMLDocument2)webBrowser.Document.DomDocument;// loads the HTML DOM
            IHTMLSelectionObject selection = HtmlDoc.selection;// Fetches the currently selected HTML Element.
            IHTMLTxtRange range = (IHTMLTxtRange)selection.createRange();
            IHTMLElement parentElement = range.parentElement();// Identifies the parent element
            targetSourceIndex = parentElement.sourceIndex;               
            //dataLocation = range.parentElement().id;                
            MessageBox.Show(range.text);//range.parentElement().sourceIndex
        }

Я использовал Встроенный веб-браузер в приложениях Winforms, который загружает HTML DOM текущей веб-страницы.

Экземпляр IHTMLElement предоставляет свойство с именем SourceIndex, которое присваивает уникальный идентификатор каждому из элементов html.

Можно хранить этот SourceIndex в БД и запрашивать содержимое в этом месте. используя следующий код.

if (webBrowser.Document != null)
            {
                IHTMLDocument2 HtmlDoc = (IHTMLDocument2)webBrowser.Document.DomDocument;
                IHTMLElement targetElement = null;
                foreach (IHTMLElement domElement in HtmlDoc.all)
                {
                    if (domElement.sourceIndex == int.Parse(node.InnerText))// fetching the persisted data from the XML file.
                    {
                        targetElement = domElement;
                        break;
                    }
                }

                MessageBox.Show(targetElement.innerText); //range.parentElement().sourceIndex
            }
...