Перевод http://www.codeproject.com/Articles/478485/Multi-Threaded-WebScraping-in-Csharp;

Парсинг сайтов — это получение интересующей информации с веб-страниц. Автор попытался сделать пошаговое руководство, начиная с основ парсинга  с помощью компонента WebBrowser  и заканчивая темами такими как выполнение логина и поддержания сессий через HTTPWebRequest.

Компонент WebBrowser

Этот контрол обеспечивает встроенный полноценный браузер в вашем приложении. Он позволяет пользователю перемещаться по веб-страницам внутри формы.

Пример: WebBrowser Download Event (событие загрузки)

  1. Добавьте контрол WebBrowser на форму. И выставите свойству Dock значение «Fill»
  2. Добавьте следующие события и код:
  3. private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        this.Text +=" a";
    }
    
    private void Form1_Load(object sender, EventArgs e)
    {
        webBrowser1.Navigate("http://jobtools.ru");
    }
  4. Функция Navigate переходит по указанному адресу
  5. Событие DocumentCompleted возникает когда вэб страница загружена
  6. Запускайте программу
  7. first

  8. Есть много способов решения вышеуказанной проблемы, например, подсчет фреймов на странице совместно с подсчетом количества срабатываний события DocumentCompleted. Это довольно таки сложно для начинающих, поэтому рассмотрим пример на основе ведения журналов.
  9. Добавьте List и модифицируйте наше событие загрузки страницы как показано ниже:
  10. List<string> hist = new List<string>();
    
    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        if (hist.Contains(webBrowser1.Url.ToString()))
            return;
        this.Text +=" a";
        hist.Add(webBrowser1.Url.ToString());
    }
    
    private void Form1_Load(object sender, EventArgs e)
    {
        webBrowser1.Navigate("http://jobtools.ru");
    }

Пример: Навигация по сайту

  1. Перед тем как создавать свой парсер сайтов, кликер-бота и т.п. необходимо разобраться с макетом документа, как искать и находить нужные блоки в документе
    1. Найдите на странице интересующий вас элемент
    2. Найдите id этого элемента на странице
  2. Для поиска id можно использовать FireFox, либо Chrome я использую последний
  3. Нажмите в Chrome F12 — Вы войдете в режим «Инструменты разработчика». Нажите на лупу и выберите интересующий вас элемент на странице
  4. two

  5. Тег привязки (якорь), выделенные на картинке выше, не имеет никакого уникального идентификатора, поэтому, если мы используем функцию GetElementByTag(“a”), то мы получим список всех ссылок на странице, для нас это не вариант
  6. Итак, попробуем поискать ближайший элемент у которого есть ID. В нашем случае далеко ходить не надо это элемент li
  7. <li id="menu-item-1469" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-1469">
  8. Теперь пишем код для выбора интересующей нас ссылки для этого находим li с id=menu-item-1469 и в нем уже ищем первую ссылку:
  9.  

                HtmlElement he = webBrowser1.Document.GetElementById("menu-item-1469");
                HtmlElementCollection hec = he.GetElementsByTagName("a");

     

  10. Теперь мы можем получить адрес нашей ссылки:
  11. webBrowser1.Navigate(hec[0].GetAttribute("href"));

Пример: Навигация по всем ссылкам на странице

  1. Для начала мы должны найти и сохранить все ссылки на странице, давайте не все ссылки а только те, что находятся в меню (id=menu-glavnaya). Для этого заведем список из строк, в который будем сохранять все значения атрибута href (сам адрес у ссылки):
  2. List<string>
    urls = new List<string>();
  3. Модифицируем событие DocumentCompleted для сохранения всех ссылок:
  4. HtmlElement he = webBrowser1.Document.GetElementById("menu-glavnaya");
    HtmlElementCollection hec = he.GetElementsByTagName("a");
    
    foreach (HtmlElement a in hec)
    {
        string href = a.GetAttribute("href");
        if (href != "http://jobtools.ru")
        {
            if (!urls.Contains(href))
                urls.Add(href);
    
        }
    }
  5. Теперь все ссылки сохранены в списке urls. Теперь код перехода по всем ссылкам:
  6. if(urls.Count > 0)       
    {    
         string u = urls[0];      
         urls.RemoveAt(0);       
         webBrowser1.Navigate(u);      
         this.Text = "Всего ссылок" + urls.Count.ToString();      
    }      
    else      
    {	MessageBox.Show("Завершено");	}

     

Пример: Заполняем и отправляем форму входа Yahoo

  1. Заходим на сайт http://mail.yahoo.com/;
  2. Находим ID формы ввода логина и пароля;
  3. Добавляем кнопку на форму и прописываем код в событии onClick
  4. htmlElement hu = webBrowser1.Document.GetElementById("username");
    hu.Focus();      
     
    hu.SetAttribute("Value","userName");      
    
    HtmlElement hp = webBrowser1.Document.GetElementById("passwd");
    hp.Focus();
    hp.SetAttribute("Value", "password"); 
  5. Для отправки формы надо найти ID кнопки входа и вызвать функцию отправки формы следующим образом:
  6. HtmlElement hf = webBrowser1.Document.GetElementById("login_form");      
     
      hf.InvokeMember("submit"); 

Пример: Установка значений для Referrer и User-Agent

  • Эти атрибуты несут в себе дополнительную информацию для веб сервера о пользователе, User-Agent — каким браузером мы пользуемся, Referrer — с какой страницы мы перешли на текущую страницу
  • Пример для изменения:
  • webBrowser1.Navigate("url", "_blank", null, "Referrer: sample user agent"); 
  • Нас интересует последний параметр — это additionalHeaders в который можно задать дополнительные заголовки HTTP
  • Список всех известных User-Agent строк можно просмотреть здесь: http://www.useragentstring.com/pages/useragentstring.php
  • Пример: Сохранить все изображения на странице

    1. Добавьте ссылку using mshtml;
    2. И используем следующий код, который сохраняет все картинки в папку с программой
    3. IHTMLDocument2 doc = (IHTMLDocument2)webBrowser1.Document.DomDocument;
      
      IHTMLControlRange imgRange = (IHTMLControlRange)((HTMLBody)doc.body).createControlRange(); 
      
      foreach (IHTMLImgElement img in doc.images)       {       
       
      imgRange.add((IHTMLControlElement)img);       
       
      imgRange.execCommand("Copy", false, null);  
      
      try{ 
          using(Bitmap bmp = (Bitmap)Clipboard.GetDataObject().GetData(DataFormats.Bitmap))            
          bmp.Save(img.nameProp + ".jpg");     
         } 
      catch (System.Exception ex)
         {  
         MessageBox.Show(ex.Message);          
         }       
      }

    Пример: Разбор капчи используя API DeathByCaptcha

    1. Подключаем ссылку using DeathByCaptcha;
    2. Используем следующий код (тут всё просто)
    3. Client client = (Client)new SocketClient(capUser, capPwd);
      try
          {           
              Captcha captcha = client.Decode(path + capName, 50); 
      
      		if (null != captcha)             
      		{ 
      		    //Captcha Solved
      		    MessageBox.Show(captcha.Text);            
              }
      		else
      		{ 
      			//Captcha Not Solved Show Error Message            
      		}          
      	}          
      	catch(DeathByCaptcha.Exception ex)          {           
      	MessageBox.Show(ex.Message); 
      } 

    Пример: Как задать Proxy для WebServer

    using Microsoft.Win32;  
    RegistryKey reg = Registry.CurrentUser.OpenSubKey(
      "Software\\Microsoft\\Windows\\CurrentVersion\\InternetSettings", true);
    
    registry.SetValue("ProxyEnable", 1); 
    
    registry.SetValue("ProxyServer", "192.168.1.1:9876");
    

    Читать продолжение:

    Парсинг сайтов на c#. Часть 1. Использование WebBrowser

    8 thoughts on “Парсинг сайтов на c#. Часть 1. Использование WebBrowser

    • 8 мая 2015 на 11:39
      Постоянная ссылка

      Спасибо за статью, пригодилась. Но Вы писали, что можно организовать «…подсчет фреймов на странице совместно с подсчетом количества срабатываний события DocumentCompleted…». Можете описать каким образом это реализовать. Спасибо.

      Ответить
    • 12 мая 2015 на 07:51
      Постоянная ссылка

      А можете показать пример как парсить статистику сервера с сайта мониторинга по типу Статус Онлайн или в Оффлайн и количество игроков?

      Ответить
      • 12 мая 2015 на 08:33
        Постоянная ссылка

        Если эта информация выводится на сайте, то это легко, дайте адрес сайта для примера.
        Помню в WoW статистику отдавал специальный скрипт на php что ли. Вообщем дайте адрес сайта, а там попробуем

        Ответить
          • 13 мая 2015 на 03:41
            Постоянная ссылка

            //Загружаем страничцу
            webBrowser1.Navigate(«http://gs4u.net/dayzm/217.23.139.34:2302.html»);

            //после загрузки страницы в DocumentCompleted парсим
            HtmlElementCollection he = webBrowser1.Document.GetElementsByTagName(«td»);
            Label1.Text = he[25].InnerText;

            выбрали все элементы td на странице, так как в вашем случае id не прописан.
            25 элемент td как раз и содержит необходимую Вам информацию.

            Я перешел на использование php для парсинга страниц, и по сравнению с ним этот вариант в статье очень уж не удобен и ограничен.

            Быстрее, функциональней делать так как описано в этом примере

            используя описанные там библиотеки

            Ответить

    Добавить комментарий

    Ваш e-mail не будет опубликован. Обязательные поля помечены *

    Нажимая на кнопку "Отправить комментарий", я даю согласие на обработку персональных данных и соглашаюсь c политикой конфиденциальности *