Разработка сайта для Вашего бизнеса. Веб дизайн. Дизайн логотипа, фирменного стиля, рекламная фотография . Комплексный рекламный креатив.

Ralex. We do the work.
На рынке с 1999го года. Средняя ценовая категория. Ориентация на эффективность решений.
Ознакомтесь с нашим портфолио
Узнайте больше о услугах
Свяжитесь с нами:
E-mail: [email protected]
Tel: (044) 587 - 84 - 78
Custom web design & дизайн и разработка сайта "под ключ"
Креативный, эффективный дизайн. Система управления сайтом (СУС).
Custom flexible разработка систем электронной коммерции
Система e-commerce разрабатывается под индивидуальные потребности. Гибкая функциональность.
Search Engine Optimzation & оптимизация под поисковые системы (SEO)
Постоянная оптимизация и мониторинг сайта в поисковых системах. Достигаем результата быстро и эффективно
Custom logo design & дизайн логотипа и фирменного стиля
Многолетний опыт. Огромное портфолио. Уникальное предложение и цена.
профессиональная рекламная фотография
креативно, смело, качественно
Custom logo design & рекламный креатив. дизайн рекламы
Многолетний опыт. Огромное портфолио. Уникальное предложение и цена.

»[C #] Введення в XPath на прикладі простого парсеру

Наша взаимовыгодная связь https://banwar.org/

Упевнений, що не раз і не два доводилося зливати який-небудь контент зі сторінок сайту. Природно, перше, що спадає на думку - це впихнути регулярні вирази де тільки можна і побільше. Люди не просто так придумали афоризм:

Деякі люди, коли стикаються з проблемою, думають «Я знаю, я вирішу її за допомогою регулярних виразів.» Тепер у них дві проблеми.

Ось і ми не зупинятиметься на них, а підемо далі. У нас є DOM. Чому б не обробляти документ як личить, а не просто як рядок html-коду? Будемо використовувати бібліотеку HtmlAgilityPack (http://htmlagilitypack.codeplex.com/). Офіційна сторінка HAP говорить нам наступне:
»This is an agile HTML parser that builds a read / write DOM and supports plain XPATH or XSLT (you actually do not HAVE to understand XPATH nor XSLT to use it, do not worry ...). It is a .NET code library that allows you to parse «out of the web» HTML files. The parser is very tolerant with «real world» malformed HTML. The object model is very similar to what proposes System.Xml, but for HTML documents (or streams). »
У міру вільному перекладі це звучить так:

Це парсер HTML, який будує доступний для читання / запису DOM і підтримує простий XPATH або XSLT (Вам не потрібно розуміти XPATH ні XSLT, щоб використовувати його, не хвилюйтеся ...). Це. NET бібліотека, яка дозволяє працювати з HTML файлами «поза мережею». Аналізатор терпимо до «реального» неправильного HTML. Об'єктна модель дуже схожа на ту, що пропонує System.Xml, але для HTML документів (або потоків).

Хоч автор і говорить, що розуміти XPath не обов'язково, необхідно хоча б знати, що це. Всезнаюча Вікіпедія дає таке визначення ( http://ru.wikipedia.org/wiki/XPath ):

XPath (XML Path Language) - мова запитів до елементів XML-документа. Розроблено для організації доступу до частин документа XML в файлах трансформації XSLT і є стандартом консорціуму W3C. XPath покликаний реалізувати навігацію по DOM в XML. У XPath використовується компактний синтаксис, відмінний від прийнятого в XML.

Вибираємо сайт для експериментів. Я взяв сайт http://rabota-i-trud.com.ua/ .
Качаємо HAP з офіційного сайту.
Відкриваємо нашу Visual Studio і створюємо новий проект.

Відкриваємо нашу Visual Studio і створюємо новий проект

Тут і далі розробка ведеться на Visual Studio 2010 Express Edition під .NET 3.5

Тепер треба додати в проект HAP.
Тепер треба додати в проект HAP
У віконці, що з'явилося вибираємо вкладку «Browse» і знаходимо бібліотеку.

У Solution Explorer в References можна побачити таке:

Залишилося тільки прописати using HtmlAgilityPack; спочатку і готово.

Всякі резюме перебувають за посиланням http://rabota-i-trud.com.ua/shortres.php . Тут же можна провести пошук по критеріям. Все як у людей.
Всякі резюме перебувають за посиланням   http://rabota-i-trud
Парсинг цього сайту складається з двох частин:

  • Знайти посилання на цікаві для нас сторінки.
  • Вибрати з цих сторінок необхідну інформацію.

Подивимося на «відмінні» риси посилань на сторінки з резюме.
Подивимося на «відмінні» риси посилань на сторінки з резюме
Відразу кидається в очі, що посилання на резюме мають атрибут class зі значенням newtitle. Переглянувши код сторінки, приходимо до висновку, що ні в яких інших елементів на сторінки атрибута class з таким значенням немає. Так що можемо використовувати його як критерій пошуку. А що якщо подивитися з іншого боку? Що якщо взяти повний шлях від кореня документа?

На малюнку він показаний в самому низу. При програмної реалізації до цього ще повернемося.
Тепер треба подивитися на сторінку з резюме і вибрати критерії пошуку DOM-вузлів.

Тут теж все виявилося не складно. Нам підходять елементи td (елементи таблиці), у який class = pad_resume.
У такій вибірці ми отримаємо

Відкинути лівий стовпець можна просто обходячи список DOM-вузлів з кроком +2 (починаючи з другого елементу).

Для початку накидаємо на форму елементи введення / виведення. Користувач повинен вводити url з критеріями вибірки, першу сторінку пошуку і останню (це 3 TextBox'a). На виході користувач отримуємо багато-багато напарсенной інформації (для простоти поставимо RichTextBox). Ще парочка рядків з описом полів введення і кнопка запуску парсинга. Виходить щось таке:
Для початку накидаємо на форму елементи введення / виведення
Пунктирні лінії - це відгомін моєї «любові» до «гумовим» дизайнам.

Тепер все-таки Кодима.
Нам знадобиться підключити кілька namespace:

using System.Net; using System.Web; using System.IO; using System.Threading;

using System.Net; using System.Web; using System.IO; using System.Threading;

Парсинг буде йти в окремому потоці. Детальніше про те, як грамотно писати багатопоточний додаток, можна прочитати в статті deface ( https://forum.xaknet.ru/showthread.php?t=11675 ). Тому, не буду зупинятися на цьому.

Нам потрібен метод для отримання HTML-коду сторінки. В Інтернеті існують сотні прикладів як це можна зробити. Візьмемо один з них і трохи допив:

public string getRequest (string url) {try {var httpWebRequest = (HttpWebRequest) WebRequest. Create (url); httpWebRequest. AllowAutoRedirect = false; // Забороняємо автоматичний редирект httpWebRequest. Method = "GET"; // Можна не вказувати, за замовчуванням використовується GET. httpWebRequest. Referer = "http://google.com"; // Реферер. Тут можна вказати будь-який URL using (var httpWebResponse = (HttpWebResponse) httpWebRequest. GetResponse ()) {using (var stream = httpWebResponse. GetResponseStream ()) {using (var reader = new StreamReader (stream, Encoding. GetEncoding (httpWebResponse. CharacterSet) )) {return reader. ReadToEnd (); }}}} Catch {return String. Empty; }}

public string getRequest (string url) {try {var httpWebRequest = (HttpWebRequest) WebRequest.Create (url); httpWebRequest.AllowAutoRedirect = false; // Забороняємо автоматичний редирект httpWebRequest.Method = "GET"; // Можна не вказувати, за замовчуванням використовується GET. httpWebRequest.Referer = "http://google.com"; // Реферер. Тут можна вказати будь-який URL using (var httpWebResponse = (HttpWebResponse) httpWebRequest.GetResponse ()) {using (var stream = httpWebResponse.GetResponseStream ()) {using (var reader = new StreamReader (stream, Encoding.GetEncoding (httpWebResponse.CharacterSet) )) {return reader.ReadToEnd (); }}}} Catch {return String.Empty; }}

Готово.

Тепер треба отриманий HTML-код обробити. Для початку створюємо об'єкт класу HtmlDocument:

HtmlAgilityPack. HtmlDocument doc = new HtmlAgilityPack. HtmlDocument ();

HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument ();

Завантажуємо в doc отриманий HTML:

doc. LoadHtml (getRequest (url));

doc.LoadHtml (getRequest (url));

Треба сказати кілька слів про синтаксис XPath, який ми будемо використовувати. Базою мови XPath є осі (нижче наведені лише ті, які були використані мною):

  • attribute :: - Повертає безліч атрибутів поточного елемента (скорочено - @).
  • descendant-or-self :: - Повертає повне безліч нащадків і поточний елемент (скорочено - //).

Повний список можна знайти за посиланням - http://ru.wikipedia.org/wiki/XPath#.D0.9E.D1.81.D0.B8

Так само є ряд функцій для роботи з множинами:

  • [] - додаткові умови вибірки
  • / - визначає рівень дерева

Повний список можна знайти за посиланням -
http://ru.wikipedia.org/wiki/XPath#....B0.D0.BC.D0.B8
Отже, необхідно скласти правило для вибірки посилань на сторінки з резюме. Ми говорили, що це елементи a з атрибутом class рівним newtitle.

  • Для початку: //
  • Тепер треба вказати, що вибираються посилання: // a
  • Але треба конкретизувати, які посилання ми вибираємо: // a []
  • Треба посилання з атрибутом class рівним newtitle: // a [@ class = 'newtitle']

Є.
При перегляді сторінок ми говорили, що можна взяти повний шлях від кореня документа:
/ html / body / center / div / div [2] / table [2] / tr / td / table [3] / tr / table / tr / td [2] / b / a
Обидва правила відповідають однаковим набором елементів.
У створеного об'єкта doc є властивість DocumentNode (вказує на верхній вузол документа). У нього ж в свою чергу є методи SelectNodes і SelectSingleNode. Перший вибирає колекцію елементів, а другий - тільки один. Нам потрібен перший метод.

HtmlNodeCollection c = doc. DocumentNode. SelectNodes ( "// a [@ class = 'newtitle']");

HtmlNodeCollection c = doc.DocumentNode.SelectNodes ( "// a [@ class = 'newtitle']");

Важливо! Цей метод може повернути null, якщо не буде знайдено елементів.
Значить треба зробити перевірку:

Далі в циклі обробляємо кожен елемент колекції. У цих елементів нас цікавить атрибут href (доступ до нього можна отримати через масив атрибутів Attributes). І, якщо він не null, то завантажуємо сторінку за цим посиланням. На завантаженої сторінці з резюме нас цікавлять елементи таблиці з атрибутом class рівним pad_resume.
Правило для вибірки буде таким:
// td [@ class = 'pad_resume']
Як говорилося раніше, нам потрібні тільки парні осередки.
Так, якщо взяти правило // td [@ class = 'list_info_resume'], то можна отримати інші дані на сторінці з резюме (Освіта, Досвід роботи, Додаткова інформація, Побажання до майбутньої роботи).

Повний код методу наведено нижче:

private void start () {my_delegate = new add_text (add_text_method); // У циклі обробляємо сторінки з first_page по last_page (ті, що вказали в полях введення) for (int i = this. First_page - 1; i & lt; this. Last_page; i ++) {string content = getRequest (tb_url. Text + this. param_separator + "p =" + i); HtmlAgilityPack. HtmlDocument doc = new HtmlAgilityPack. HtmlDocument (); doc. LoadHtml (content); // Отримуємо список посилань на сторінки з резюме HtmlNodeCollection c = doc. DocumentNode. SelectNodes ( "// a [@ class = 'newtitle']"); if (c! = null) {// Обробляємо кожну сторінку (Парс з неї вибрані дані) foreach (HtmlNode n in c) {if (n. Attributes [ "href"]! = null) {// Завантажуємо сторінку з резюме string u = main_url + n. Attributes [ "href"]. Value; string res_cn = getRequest (u); // Парс сторінку з резюме HtmlAgilityPack. HtmlDocument d = new HtmlAgilityPack. HtmlDocument (); d. LoadHtml (res_cn); // Вибираємо комірки з потрібними даними HtmlNodeCollection pads = d. DocumentNode. SelectNodes ( "// td [@ class = 'pad_resume']"); if (pads! = null) {// Нам потрібні тільки парні осередки int j = 1; while (j & lt; pads. Count) {// Записуємо текст з осередку в RTB (прибираємо все зайве через trim) rtb_output. Invoke (my_delegate, new object [] {pads [j]. InnerText. Trim () + ";"}); j = j + 2; } Rtb_output. Invoke (my_delegate, new object [] { "\ n"}); }}}}} A_delegate = new set_text (set_text_method); // Прибираємо дублі rtb_output. Invoke (a_delegate, new object [] {array_unique (rtb_output. Lines)}); \ // Робимо елементи форми активними tlp_main. Enabled = true; // Завершуємо потік tr. Abort (); }

private void start () {my_delegate = new add_text (add_text_method); // У циклі обробляємо сторінки з first_page по last_page (ті, що вказали в полях введення) for (int i = this.first_page - 1; i & lt; this.last_page; i ++) {string content = getRequest (tb_url.Text + this .param_separator + "p =" + i); HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument (); doc.LoadHtml (content); // Отримуємо список посилань на сторінки з резюме HtmlNodeCollection c = doc.DocumentNode.SelectNodes ( "// a [@ class = 'newtitle']"); if (c! = null) {// Обробляємо кожну сторінку (Парс з неї вибрані дані) foreach (HtmlNode n in c) {if (n.Attributes [ "href"]! = null) {// Завантажуємо сторінку з резюме string u = main_url + n.Attributes [ "href"]. Value; string res_cn = getRequest (u); // Парс сторінку з резюме HtmlAgilityPack.HtmlDocument d = new HtmlAgilityPack.HtmlDocument (); d.LoadHtml (res_cn); // Вибираємо комірки з потрібними даними HtmlNodeCollection pads = d.DocumentNode.SelectNodes ( "// td [@ class = 'pad_resume']"); if (pads! = null) {// Нам потрібні тільки парні осередки int j = 1; while (j & lt; pads.Count) {// Записуємо текст з осередку в RTB (прибираємо все зайве через trim) rtb_output.Invoke (my_delegate, new object [] {pads [j] .InnerText.Trim () + ";" }); j = j + 2; } Rtb_output.Invoke (my_delegate, new object [] { "\ n"}); }}}}} A_delegate = new set_text (set_text_method); // Прибираємо дублі rtb_output.Invoke (a_delegate, new object [] {array_unique (rtb_output.Lines)}); \ // Робимо елементи форми активними tlp_main.Enabled = true; // Завершуємо потік tr.Abort (); }

Результат роботи програми видно на малюнку нижче:
Результат роботи програми видно на малюнку нижче:

Як бачимо, робота з Xpath дуже проста і дозволяє отримати необхідний результат без особливих зусиль. У цьому невеликому мануале показана мала частина можливостей XPath і HAP. Закрите те залишається на розгляд читачів.
завантажити вихідні
завантажити текст

(С) K_S for XakNet.Ru

agility , C # , HAP , html , pack , parser , xpath

Чому б не обробляти документ як личить, а не просто як рядок html-коду?
А що якщо подивитися з іншого боку?
Що якщо взяти повний шлях від кореня документа?
Php?
Категории
  • Биология
  • Математика
  • Краеведению
  • Лечебная
  • Наука
  • Физике
  • Природоведение
  • Информатика
  • Новости

  • Новости
    https://banwar.org/
    Наша взаимовыгодная связь https://banwar.org/. Запустив новый сайт, "Пари Матч" обещает своим клиентам незабываемый опыт и возможность выиграть крупные суммы.


    Наши клиенты
    Клиенты

    Быстрая связь

    Тел.: (044) 587-84-78
    E-mail: [email protected]

    Имя:
    E-mail:
    Телефон:
    Вопрос\Комментарий: