Se
Содержание:
Loading Url
Loading a url is very similar to the way you would load the html from a file.
// Assuming you installed from Composer:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadFromUrl('http://google.com');
$html = $dom->outerHtml;
// or
$dom->loadFromUrl('http://google.com');
$html = $dom->outerHtml; // same result as the first example
loadFromUrl will, by default, use an implementation of the to do the HTTP request and a default implementation of to create the body of the request. You can easely implement your own version of either the client or request to use a custom HTTP connection when using loadFromUrl.
// Assuming you installed from Composer:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
use App\Services\MyClient;
$dom = new Dom;
$dom->loadFromUrl('http://google.com', null, new MyClient());
$html = $dom->outerHtml;
As long as the client object implements the interface properly it will use that object to get the content of the url.
C#
Let’s move to the C# library to process HTML.
AngleSharp
AngleSharp is quite simply the default choice for whenever you need a modern HTML parser for a C# project. In fact, it does not just parse HTML5, but also its most used companions: CSS and SVG. There is also an extension to integrate scripting in the contest of parsing HTML documents: both C# and JavaScript, based on Jint. Which means that you can parse HTML documents after they have been modified by JavaScript. Both the JavaScript included in the page or a script you add yourself.
AngleSharp fully support modern conventions for easy manipulation, like CSS selectors and jQuery-like constructs. But it is also well integrated in the .NET world, with support for LINQ for DOM elements. The author mention that it may want to evolving it in , for the moment it can do simple things like submitting forms.
The following example, from the documentation, shows a few features of AngleSharp.
var parser = new HtmlParser();
var document = parser.Parse("<ul><li>First item<li>Second item<li class='blue'>Third item!<li class='blue red'>Last item!</ul>");
//Do something with LINQ
var blueListItemsLinq = document.All.Where(m => m.LocalName == "li" && m.ClassList.Contains("blue"));
//Or directly with CSS selectors
var blueListItemsCssSelector = document.QuerySelectorAll("li.blue");
Console.WriteLine("Comparing both ways ...");
Console.WriteLine();
Console.WriteLine("LINQ:");
foreach (var item in blueListItemsLinq)
Console.WriteLine(item.Text());
Console.WriteLine();
Console.WriteLine("CSS:");
foreach (var item in blueListItemsCssSelector)
Console.WriteLine(item.Text());
The documentation may contain all the information you need, but it certainly could use a better organization. For the most part it is delivered within the GitHub project, but there are also .
HtmlAgilityPack
HtmlAgilityPack was once considered the default choice for HTML parsing with C#. Although some says for the lack of better alternatives, because the quality of the code was low. In any case it was essentially abandoned for the last few years, until it was recently revived by ZZZ Projects.
In terms of features and quality it is quite lacking, at least compared to AngleSharp. Support for CSS selector, necessary for modern HTML parsing, and support for .NET Standard, necessary for modern C# projects, are on the roadmap. On the same document there is also planned a cleanup of the code.
If you are in need for things like XPath HtmlAgilityPack should be your best choice. In other cases, I do not think it is the best choice right now, unless you are already using it. That is especially true since there is no documentation. Though the new maintainer and the prospect for better features are a good reason to keep using it, if you are already a user.
// Load an HTML document
var url = "http://html-agility-pack.net/";
var web = new HtmlWeb();
var doc = web.Load(url);
// Get value with XPath
var value = doc.DocumentNode
.SelectNodes("//td/input")
.First()
.Attributes.Value;
Парсите страницы сайтов в структуры данных
Что такое Диггернаут и что такое диггер?
Диггернаут — это облачный сервис для парсинга сайтов, сбора информации и других ETL (Extract, Transform, Load) задач. Если ваш бизнес лежит в плоскости торговли и ваш поставщик не предоставляет вам данные в нужном вам формате, например в csv или excel, мы можем вам помочь избежать ручной работы, сэкономив ваши время и деньги!
Все, что вам нужно сделать — создать парсер (диггер), крошечного робота, который будет парсить сайты по вашему запросу, извлекать данные, нормализовать и обрабатывать их, сохранять массивы данных в облаке, откуда вы сможете скачать их в любом из доступных форматов (например, CSV, XML, XLSX, JSON) или забрать в автоматическом режиме через наш API.
Какую информацию может добывать Диггернаут?
- Цены и другую информацию о товарах, отзывы и рейтинги с сайтов ритейлеров.
- Данные о различных событиях по всему миру.
- Новости и заголовки с сайтов различных новостных агентств и агрегаторов.
- Данные для статистических исследований из различных источников.
- Открытые данные из государственных и муниципальных источников. Полицейские сводки, документы по судопроизводству, росреест, госзакупки и другие.
- Лицензии и разрешения, выданные государственными структурами.
- Мнения людей и их комментарии по определенной проблематике на форумах и в соцсетях.
- Информация, помогающая в оценке недвижимости.
- Или что-то иное, что можно добыть с помощью парсинга.
Должен ли я быть экспертом в программировании?
Если вы никогда не сталкивались с программированием, вы можете использовать наш специальный инструмент для построения конфигурации парсера (диггера) — Excavator. Он имеет графическую оболочку и позволяет работать с сервисом людям, не имеющих теоретических познаний в программировании. Вам нужно лишь выделить данные, которые нужно забрать и разместить их в структуре данных, которую создаст для вас парсер. Для более простого освоения этого инструмента, мы создали серию видео уроков, с которыми вы можете ознакомиться в документации.
Если вы программист или веб-разработчик, знаете что такое HTML/CSS и готовы к изучению нового, для вас мы приготовили мета-язык, освоив который вы сможете решать очень сложные задачи, которые невозможно решить с помощью конфигуратора Excavator. Вы можете ознакомиться с документацией, которую мы снабдили примерами из реальной жизни для простого и быстрого понимания материала.
Если вы не хотите тратить свое время на освоение конфигуратора Excavator или мета-языка и хотите просто получать данные, обратитесь к нам и мы создадим для вас парсер в кратчайшие сроки.
Использование Selenium на C#
Самый распостраненный способ автоматизировать любые действия с вебсайтом — использование библиотеки Selenium. Эта библиотека позволяет запустить браузер и управлять всеми действиями в нем. Поддерживаются все распостраненные браузеры.
Подключение Selenium к проекту
В контекстном меню проекта выбираем пункт «Manage NuGet Packages…»
Далее на вкладке «Browse» находим и устанавливаем пакеты Selenium.WebDriver и Selenium.WebDriver.ChromeDriver. Первый пакет — сама библиотека, второй добавляет в папку с собранным проектом драйвер к хрому ChromeDriver.exe.
Автоматизация действий с помощью Selenium
В качестве тестовой задачи попробуем на этом блоге открыть первую страницу с результатами поиска по запросу «C#» и на консоль вывести заголовки и адреса найденных статей.
Начнем с того, что откроем браузер и перейдем на главную страницу сайта.
using OpenQA.Selenium; using OpenQA.Selenium.Chrome; ... IWebDriver driver = new ChromeDriver(); driver.Url = @"http://lsreg.ru";
Теперь нужно найти инпут для ввода критерия поиска и ввести в него текст. Поиск элементов на странице осуществляется с помощью методов IWebDriver.FindElement и IWebDriver.FindElements. Эти методы умеют искать по множеству критериев: тег, css класс, xpath и другие.
Поиск элементов по XPath
XPath — это язык запросов к дереву элементов. Вот как выглядит запрос дива с id=»my_div»:
.//div
Здесь точка вначале запроса означает, что поиск осуществляется из корня документа. Без точки поиск осущствлялся бы только в контексте текущего элемента. Двойной слеш означает любое количество элементов. Одинарный слеш означал бы, что див лежит прямо в корне документа. Пара примеров для наглядкости:
.//div//a - все ссылки внутри дива .//div/a - ссылки на первом уровне вложенности
Кроме id фильтровать можно и по другим атрибутам.
Действия с элементами страницы
Метод FindElement возвращает экземпляр IWebElement. Для ввода текста используется метод SendKeys, для клика есть метод Click.
Находим инпут и вводим в него строку поиска
driver.FindElement(By.XPath(@".//div/form/input")).SendKeys("c#");
Кликаем на кнопку поиска
driver.FindElement(By.XPath(@".//input")).Click(); Thread.Sleep(3000);
Sleep нужен для того, чтобы результаты поиска успели отобразиться.
Теперь находим все ссылки внутри заголовков и отображаем их текст и href
var links = driver.FindElements(By.XPath(".//h2/a"));
foreach (IWebElement link in links)
Console.WriteLine("{0} - {1}", link.Text, link.GetAttribute("href"));
Получаем вот такой результат
Определение «скрытых» данных на уровне ключевых слов
В Google Analytics есть возможность подгрузить данные из Search Console. Но вы не увидите ничего нового — все те же страницы, CTR, позиции и показы. А было бы интересно посмотреть, какой процент отказов при переходе по тем или иным ключевым словам и, что еще интересней, сколько достигнуто целей по ним.
Тут поможет шаблон от Sarah Lively, который описан в статье для MOZ.
Для начала работы установите дополнения для Google Sheets:
- Google Analytics Spreadsheet Add-on;
- Search Analytics for Sheets (если вы использовали первые два шаблона, то это дополнение у вас уже есть).
Шаг 1. Настраиваем выгрузку данных из Google Analytics
Создайте новую таблицу, откройте меню «Дополнения» / «Google Analytics» и выберите пункт «Create new report».
Заполняем параметры отчета:
- Name — «Organic Landing Pages Last Year»;
- Account — выбираем аккаунт;
- Property — выбираем ресурс;
- View — выбираем представление.
Нажимаем «Create report». Появляется лист «Report Configuration». Вначале он выглядит так:
Но нам нужно, чтобы он выглядел так (параметры выгрузки вводим вручную):
Просто скопируйте и вставьте параметры отчетов (и удалите в поле Limit значение 1000):
| Report Name | Organic Landing Pages Last Year | Organic Landing Pages This Year |
| View ID | //здесь будет ваш ID в GA!!! | //здесь будет ваш ID в GA!!! |
| Start Date | 395daysAgo | 30daysAgo |
| End Date | 365daysAgo | yesterday |
| Metrics | ga:sessions, ga:bounces, ga:goalCompletionsAll | ga:sessions, ga:bounces, ga:goalCompletionsAll |
| Dimensions | ga:landingPagePath | ga:landingPagePath |
| Order | -ga:sessions | -ga:sessions |
| Filters | ||
| Segments | sessions::condition::ga:medium==organic | sessions::condition::ga:medium==organic |
После этого в меню «Дополнения» / «Google Analytics» нажмите «Run reports». Если все хорошо, вы увидите такое сообщение:
Также появится два новых листа с названиями отчетов.
Шаг 2. Выгрузка данных из Search Console
Работаем в том же файле. Переходим на новый лист и запускаем дополнение Search Analytics for Sheets.
Параметры выгрузки:
- Verified Site — указываем сайт;
- Date Range — задаем тот же период, что и в отчете «Organic Landing Pages This Year» (в нашем случае — последний месяц);
- Group By — «Query», «Page»;
- Aggregation Type — «By Page»;
- Results Sheet — выбираем текущий «Лист 1».
Выгружаем данные и переименовываем «Лист 1» на «Search Console Data». Получаем такую таблицу:
Для приведения данных в сопоставимый с Google Analytics вид меняем URL на относительные — удаляем название домена (через функцию замены меняем домен на пустой символ).
После изменения URL должны иметь такой вид:
Шаг 3. Сводим данные из Google Analytics и Search Console
Копируем шаблон Keyword Level Data. Открываем его и копируем лист «Keyword Data» в наш рабочий файл. В столбцы «Page URL #1» и «Page URL #2» вставляем относительные URL страниц, по которым хотим сравнить статистику.
По каждой странице подтягивается статистика из Google Analytics, а также 6 самых популярных ключей, по которым были переходы. Конечно, это не детальная статистика по каждому ключу, но все же это лучше, чем ничего.
При необходимости вы можете доработать шаблон — изменить показатели, количество выгружаемых ключей и т. п. Как это сделать, детально описано в оригинальной статье.
Как видите, для работы с ключами не обязательно сразу доставать кошелек. Есть немало простых решений. Следите за нашими публикациями — мы еще не раз поделимся полезностями.
JSON Explained
What is JSON?
JSON stands for «JavaScript Object Notation» and is pronounced «Jason» (like in the Friday the 13th movies). It’s meant to be a human-readable and compact solution to represent a complex data structure and facilitate data-interchange between systems.
Why use JSON?
There are tons of reasons why you would want to use JSON:
- It’s human readable… if it’s properly formatted 😛
- It’s compact because it doesn’t use a full markup structure, unlike XML
- It’s easy to parse, especially in JavaScript
- A gazillion JSON libraries are available for most programming languages
- The data structure is easy to understand
The JSON format
There are just a few rules that you need to remember:
- Objects are encapsulated within opening and closing brackets { }
- An empty object can be represented by { }
- Arrays are encapsulated within opening and closing square brackets
- An empty array can be represented by
- A member is represented by a key-value pair
- The key of a member should be contained in double quotes. (JavaScript does not require this. JavaScript and some parsers will tolerate single-quotes)
- Each member should have a unique key within an object structure
- The value of a member must be contained in double quotes if it’s a string (JavaScript and some parsers will tolerates single-quotes)
- Boolean values are represented using the true or false literals in lower case
- Number values are represented using double-precision floating-point format. Scientific notation is supported
- Numbers should not have leading zeroes
- «Offensive» characters in a string need to be escaped using the backslash character
- Null values are represented by the null literal in lower case
- Other object types, such as dates, are not properly supported and should be converted to strings. It becomes the responsibility of the parser/client to manage this
- Each member of an object or each array value must be followed by a comma if it’s not the last one
- The common extension for json files is ‘.json’
- The mime type for json files is ‘application/json’
JSON in JavaScript
Because JSON derives from JavaScript, you can parse a JSON string simply by invoking the eval() function. The JSON string needs to be wrapped by parenthesis, else it will not work! This is the #1 problem when programmers first start to manipulate JSON strings. That being said, DON’T do this!
Example using the ‘dangerous’ eval():
As pointed out by M. Clement at Inimino, a better and more secure way of parsing a JSON string
is to make use of JSON.parse(). The eval() function leaves the door open to all JS expressions potentially creating side effects or security issues, whereas
JSON.parse() limits itself to just parsing JSON. JSON.parse() is available natively in . If you need to support older browser,
make use of an external JavaScript library such as Douglas Crockford’s json2.js.
Example using JSON.parse():
If you want to create a JSON string representation of your JavaScript object, make use of the JSON.stringify() function.
Example using JSON.stringify():
You can also create JavaScript objects using the JSON syntax directly in your code.
Example of creating a JavaScript object using ‘JSON’ syntax:
Programming languages and JSON
The website JSON.org maintains an extensive list of JSON libraries and they are categorized in programming languages. Unfortunately, there are so many libraries out there that it’s very hard to chose one! Note that VERY few JSON libraries have strict adherence to the JSON specification and this can lead to parsing problems between systems.
These are my recommended JSON libraries:
- C++: JsonCpp
- C# (.Net): Json.NET
- JAVA: JSON.smart,JSON-lib
Other useful JSON resources
- JSON.org — Excellent overall explanation and list of many JSON libraries
- Wikipedia — Brief explanation of JSON
- TheServerSide.net — A list of JSON resource guide on TheServerSide.com
Loading Files
You may also seamlessly load a file into the dom instead of a string, which is much more convenient and is how I except most developers will be loading the html. The following example is taken from our test and uses the «big.html» file found there.
// Assuming you installed from Composer:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadFromFile('tests/data/big.html');
$contents = $dom->find('.content-border');
echo count($contents); // 10
foreach ($contents as $content)
{
// get the class attr
$class = $content->getAttribute('class');
// do something with the html
$html = $content->innerHtml;
// or refine the find some more
$child = $content->firstChild();
$sibling = $child->nextSibling();
}
This example loads the html from big.html, a real page found online, and gets all the content-border classes to process. It also shows a few things you can do with a node but it is not an exhaustive list of methods that a node has available.
Синтаксический анализатор
- Легкость расширения при изменении грамматики
- Возможность описывать подробные сообщения об ошибках
- Возможность заглядывать вперед на неограниченное количество позиций
- Автоматическое отслеживание положения в исходном коде
- Лаконичность, близость к исходной грамматике
- Описание — один конкретный узел:
- Повторение — один конкретный узел повторяется многократно, возможно с разделителем:
- Альтернатива — выбор из нескольких узлов
— Как это, просто вызываются по порядку? А как же опережающие проверки? Например, так:
- Первой вызывается альтернатива .
- Идентификатор успешно совпадает.
- Дальше идет точка, а ожидается знак «равно». Однако с идентификатора могут начинаться и другие правила, поэтому ошибка не выбрасывается.
- Правило assign откатывает состояние назад и пробует дальше.
- Вызывается альтернатива .
- Идентификатор и точка успешно совпадают. В грамматике нет других правил, которые начинаются с идентификатора и точки, поэтому дальнейшие ошибки не имеет смысл пытаться обработать откатыванием состояния.
- Число не является идентификатором, поэтому выкидывается ошибка.
- Откат состояния — очень дешевая операция
- Легко управлять тем, до куда можно откатываться
- Легко отображать детальные сообщения об ошибках
- Не требуются никакие внешние библиотеки
- Небольшой объем генерируемого кода
- Реализация парсера вручную занимает время
- Сложность написания и оптимальность работы зависят от качества грамматики
- Леворекурсивные грамматики следует разруливать самостоятельно
Options
You can also set parsing option that will effect the behavior of the parsing engine. You can set a global option array using the method in the object or a instance specific option by adding it to the method as an extra (optional) parameter.
// Assuming you installed from Composer:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
use PHPHtmlParser\Options;
$dom = new Dom;
$dom->setOptions(
// this is set as the global option level.
(new Options())
->setStrict(true)
);
$dom->loadFromUrl('http://google.com',
(new Options())->setWhitespaceTextNode(false) // only applies to this load.
);
$dom->loadFromUrl('http://gmail.com'); // will not have whitespaceTextNode set to false.
At the moment we support 12 options.
Strict
Strict, by default false, will throw a if it find that the html is not strictly compliant (all tags must have a closing tag, no attribute with out a value, etc.).
whitespaceTextNode
The whitespaceTextNode, by default true, option tells the parser to save textnodes even if the content of the node is empty (only whitespace). Setting it to false will ignore all whitespace only text node found in the document.
enforceEncoding
The enforceEncoding, by default null, option will enforce an character set to be used for reading the content and returning the content in that encoding. Setting it to null will trigger an attempt to figure out the encoding from within the content of the string given instead.
cleanupInput
Set this to to skip the entire clean up phase of the parser. If this is set to true the next 3 options will be ignored. Defaults to .
removeScripts
Set this to to skip removing the script tags from the document body. This might have adverse effects. Defaults to .
removeStyles
Set this to to skip removing of style tags from the document body. This might have adverse effects. Defaults to .
preserveLineBreaks
Preserves Line Breaks if set to . If set to line breaks are cleaned up as part of the input clean up process. Defaults to .
removeDoubleSpace
Set this to if you want to preserve whitespace inside of text nodes. It is set to by default.
removeSmartyScripts
Set this to if you want to preserve smarty script found in the html content. It is set to by default.
htmlSpecialCharsDecode
By default this is set to . Setting this to will apply the php function too all attribute values and text nodes.
selfClosing
This option contains an array of all self closing tags. These tags must be self closing and the parser will force them to be so if you have strict turned on. You can update this list with any additional tags that can be used as a self closing tag when using strict. You can also remove tags from this array or clear it out completly.
noSlash
This option contains an array of all tags that can not be self closing. The list starts off as empty but you can add elements as you wish.