Написание парсера с нуля: так ли страшен черт?
Содержание:
- Options
- How to access the HTML element’s attributes?
- Our Sponsors
- Google Фото – лучшее бесплатное хранилище для фото и видео
- Парсинг постраничной навигации и получение ссылки на следующую страницу
- Private Tunnel
- Loading URLs
- Парсеры сайтов в зависимости от используемой технологии
- Синтаксический анализатор
- About WhichBrowser
- Enable result caching
- Version 3.0.0-alpha1 (2016-07-25)
- Шаг 2 – Основы HTML парсинга
- Скрипт Human Emulator парсинга HTML-страницы с использованием XPath
- Learn more
- Version 4.4.0 (2020-04-10)
- Истории успешных бизнесменов
- Tips
- Неправильная кодировка при использовании cURL
- Делаем запросы
- API Reference
Options
It is possible to set additional options by passing an array as the second parameter when creating the object.
Disabling detection of bots
In some cases you may want to disable the detection of bots. This allows the bot the deliberately fool WhichBrowser, so you can pick up the identity of useragent what the bot tries to mimic. This is especially handy when you want to use WhichBrowser to switch between different variants of your website and want to make sure crawlers see the right variant of the website. For example, a bot that mimics a mobile device will see the mobile variant of you site.
$result = new WhichBrowser\Parser(getallheaders(), );
How to access the HTML element’s attributes?
$value = $e->href;
$e->href = ‘my link’;
$e->href = null;
if(isset($e->href))
echo ‘href exist!’;
$html = str_get_html(«<div>foo <b>bar</b></div>»);
$e = $html->find(«div», );
echo $e->tag;
echo $e->outertext;
echo $e->innertext;
echo $e->plaintext;
Attribute Name | Usage |
---|---|
$e->tag | Read or write the tag name of element. |
$e->outertext | Read or write the outer HTML text of element. |
$e->innertext | Read or write the inner HTML text of element. |
$e->plaintext | Read or write the plain text of element. |
echo $html->plaintext;
$e->outertext = ‘<div class=»wrap»>’ . $e->outertext . ‘<div>’;
$e->outertext = »;
$e->outertext = $e->outertext . ‘<div>foo<div>’;
$e->outertext = ‘<div>foo<div>’ . $e->outertext;
Our Sponsors
Our backers and sponsors help to ensure the quality and timely development of the Parse Platform.
Parse Server works with the Express web application framework. It can be added to existing web applications, or run by itself.
Google Фото – лучшее бесплатное хранилище для фото и видео
Парсинг постраничной навигации и получение ссылки на следующую страницу
Напишем новую функцию и по традиции разберём её позже
function getNextLink($link){ $url="https://www.bing.com/search"; $content= file_get_contents($url.$link); libxml_use_internal_errors(true); $mydom = new DOMDocument(); $mydom->preserveWhiteSpace = false; $mydom->resolveExternals = false; $mydom->validateOnParse = false; $mydom->loadHTML($content); $xpath = new DOMXpath($mydom); $page = $xpath->query("//*/../following::li/a"); foreach ($page as $p){ $nextlink=$p->getAttribute('href'); } return $nextlink; }
Почти идентичная функция, изменился только xpath запрос. получаем элемент с классом ( это класс активной
кнопки постраничной навигации), поднимаемся на элемент вверх по dom дереву, получаем первый соседний элемент и получаем в нём ссылку. Эта и есть ссылка на
следующую страницу.
Private Tunnel
Loading URLs
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 easily 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.
Парсеры сайтов в зависимости от используемой технологии
Парсеры на основе Python и PHP
Такие парсеры создают программисты. Без специальных знаний сделать парсер самостоятельно не получится. На сегодня самый популярный язык для создания таких программ Python. Разработчикам, которые им владеют, могут быть полезны:
- библиотека Beautiful Soup;
- фреймворки с открытым исходным кодом Scrapy, Grab и другие.
Заказывать разработку парсера с нуля стоит только для нестандартных задач. Для большинства целей можно подобрать готовые решения.
Парсеры-расширения для браузеров
Парсить данные с сайтов могут бесплатные расширения для браузеров. Они извлекают данные из html-кода страниц при помощи языка запросов Xpath и выгружают их в удобные для дальнейшей работы форматы — XLSX, CSV, XML, JSON, Google Таблицы и другие. Так можно собрать цены, описания товаров, новости, отзывы и другие типы данных.
Примеры расширений для Chrome: Parsers, Scraper, Data Scraper, kimono.
Парсеры сайтов на основе Excel
В таких программах парсинг с последующей выгрузкой данных в форматы XLS* и CSV реализован при помощи макросов — специальных команд для автоматизации действий в MS Excel. Пример такой программы — ParserOK. Бесплатная пробная версия ограничена периодом в 10 дней.
Парсинг при помощи Google Таблиц
В Google Таблицах парсить данные можно при помощи двух функций — importxml и importhtml.
Функция IMPORTXML импортирует данные из источников формата XML, HTML, CSV, TSV, RSS, ATOM XML в ячейки таблицы при помощи запросов Xpath. Синтаксис функции:
IMPORTXML("https://site.com/catalog"; "//a/@href") IMPORTXML(A2; B2)
Расшифруем: в первой строке содержится заключенный в кавычки url (обязательно с указанием протокола) и запрос Xpath.
Знание языка запросов Xpath для использования функции не обязательно, можно воспользоваться опцией браузера «копировать Xpath»:
Вторая строка указывает ячейки, куда будут импортированы данные.
IMPORTXML можно использовать для сбора метатегов и заголовков, количества внешних ссылок со страницы, количества товаров на странице категории и других данных.
У IMPORTHTML более узкий функционал — она импортирует данные из таблиц и списков, размещенных на странице сайта. Синтаксис функции:
IMPORTHTML("https://https://site.com/catalog/sweets"; "table"; 4) IMPORTHTML(A2; B2; C2)
Расшифруем: в первой строке, как и в предыдущем случае, содержится заключенный в кавычки URL (обязательно с указанием протокола), затем параметр «table», если хотите получить данные из таблицы, или «list», если из списка. Числовое значение (индекс) означает порядковый номер таблицы или списка в html-коде страницы.
Синтаксический анализатор
- Легкость расширения при изменении грамматики
- Возможность описывать подробные сообщения об ошибках
- Возможность заглядывать вперед на неограниченное количество позиций
- Автоматическое отслеживание положения в исходном коде
- Лаконичность, близость к исходной грамматике
- Описание — один конкретный узел:
- Повторение — один конкретный узел повторяется многократно, возможно с разделителем:
- Альтернатива — выбор из нескольких узлов
— Как это, просто вызываются по порядку? А как же опережающие проверки? Например, так:
- Первой вызывается альтернатива .
- Идентификатор успешно совпадает.
- Дальше идет точка, а ожидается знак «равно». Однако с идентификатора могут начинаться и другие правила, поэтому ошибка не выбрасывается.
- Правило assign откатывает состояние назад и пробует дальше.
- Вызывается альтернатива .
- Идентификатор и точка успешно совпадают. В грамматике нет других правил, которые начинаются с идентификатора и точки, поэтому дальнейшие ошибки не имеет смысл пытаться обработать откатыванием состояния.
- Число не является идентификатором, поэтому выкидывается ошибка.
- Откат состояния — очень дешевая операция
- Легко управлять тем, до куда можно откатываться
- Легко отображать детальные сообщения об ошибках
- Не требуются никакие внешние библиотеки
- Небольшой объем генерируемого кода
- Реализация парсера вручную занимает время
- Сложность написания и оптимальность работы зависят от качества грамматики
- Леворекурсивные грамматики следует разруливать самостоятельно
About WhichBrowser
But why almost completely useless and not completely useless?
Well, there is always an exception to the rule. There are valid reasons to do browser sniffing: to improve the user experience or to gather intelligence about which browsers are used on your website. My website is html5test.com and I wanted to know which score belongs to which browser. And to do that you need a browser sniffing library.
Why is it extremely complicated?
Because everybody lies. Seriously, there is not a single browser that is completely truthful. Almost all browsers say they are Netscape 5 and almost all WebKit browsers say they are based on Gecko. Even Internet Explorer 11 now no longer claims to be IE at all, but instead an unnamed browser that is like Gecko. And it gets worse. That is why it is complicated.
What kind of information does it give?
You get a nice object which has information about the browser, rendering engine, os and device. It gives you names and versions and even device manufacturer and model. And WhichBrowser is pretty tenacious. It gives you info that others don’t. For example:
Android is never mentioned
Despite the useragent header claiming to be a Series40 device, we know it’s actually running the Asha Platform and we also know that OviBrowser has been renamed to Nokia Xpress.
The useragent header looks like Opera 11.10 on Linux, but we know it’s Opera Mini. We can even figure out the real operating system and device model from other headers.
Enable result caching
WhichBrowser supports PSR-6 compatible cache adapters for caching results between requests. Using a cache is especially useful if you use WhichBrowser on every page of your website and a user visits multiple pages. During the first visit the headers will be parsed and the result will be cached. Upon further visits, the cached results will be used, which is much faster than having to parse the headers again and again.
For example, if you want to enable a memcached based cache you need to install an extra composer package:
And change the call to WhichBrowser/Parser as follows:
$client = new \Memcached(); $client->addServer('localhost', 11211); $pool = new \Cache\Adapter\Memcached\MemcachedCachePool($client); $result = new WhichBrowser\Parser(getallheaders(), );
or
$client = new \Memcached(); $client->addServer('localhost', 11211); $pool = new \Cache\Adapter\Memcached\MemcachedCachePool($client); $result = new WhichBrowser\Parser(); $result->setCache($pool); $result->analyse(getallheaders());
You can also specify after how many seconds a cached result should be discarded. The default value is 900 seconds or 15 minutes. If you think WhichBrowser uses too much memory for caching, you should lower this value. You can do this by setting the option or passing it as a second parameter to the function.
Version 3.0.0-alpha1 (2016-07-25)
Added
- Added support for and types. These will now be represented as strings
(instead of instances) similar to other builtin types. - Added support for class constant visibility. The node now has a subnode
holding the visibility modifier, as well as , and
methods. The constructor changed to accept the additional subnode. - Added support for nullable types. These are represented using a new node
with a single subnode. - Added support for short array destructuring syntax. This means that nodes may now
appear as the left-hand-side of assignments and foreach value targets. Additionally the array
items may now contain values if elements are skipped. - Added support for keys in list() destructuring. The subnode has been renamed
to and now contains s instead of plain variables. - Added support for multi-catch. The subnode has been renamed to and
is now an array of s. -
now supports lengths and negative offsets. This brings it in line with
functionality.
Changed
Due to PHP 7.1 support additions described above, the node structure changed as follows:
- and types are now stored as strings if the PHP 7 parser is used.
- The constructor changed to accept an additional subnode.
- The subnode may now contain elements (destructuring).
- The subnode has been renamed to and now contains s instead of
plain variables. - The subnode has been renamed to and is now an array of s.
Additionally the following changes were made:
- The subnode on , and has been renamed to . The
subnode has retained for backwards compatibility and is populated to the same value as
. However, writes to will not update . - The subnode has been replaced with a subnode that holds an
explicit node. This allows for more accurate attribute assignment. - The constructor now has the same form as the and constructors: It
takes an array of subnodes. Unlike classes/interfaces, traits can only have a subnode. - The now prints class/method/property/constant modifiers, as well as the include and
use type in a textual representation, instead of only showing the number. - All methods on are now protected. Previously most of them were public.
Removed
- Removed support for running on PHP 5.4. It is however still possible to parse PHP 5.2-5.4 code
while running on a newer version. - The deprecated and methods have been removed.
- The deprecated , and methods have been removed.
Шаг 2 – Основы HTML парсинга
Эта библиотека, очень проста в использовании, но все же,
необходимо разобрать некоторые основы, перед тем как ее использовать.
Загрузка HTML
$html = new simple_html_dom(); // Load from a string $html->load('<html><body><p>Hello World!</p><p>We're here</p></body></html>'); // Load a file $html->load_file('http://sitear.ru/');
Все просто, вы можете создать объект, загружая HTML из
строки. Или, загрузить HTML код из файла. Загрузить файл вы можете по URL адресу, или
с вашей локальной файловой системы (сервера).
Важно помнить: Метод
load_file(), работает на использовании PHP функции file_get_contents. Если в
вашем файле php.ini, параметр allow_url_fopen
не установлен как true,
вы не сможете получать HTML файлы по удаленному адресу
Но, вы сможете загрузить эти
файлы, используя библиотеку CURL. Далее, прочитать содержимое, используя метод load().
Получение доступа к HTML DOM объектам
Предположим у нас уже есть DOM объект,
структурой, как на картинке выше. Вы можете начать работать с ним, используя
метод find(), и создавая коллекции. Коллекции – это группы объектов, найденные
с помощью селекторов – синтаксис в чем-то схож с jQuery.
<html> <body> <p>Hello World!</p> <p>We're Here.</p> </body> </html>
Используя этот пример HTML кода, мы узнаем, как получить доступ
к информации заключенной во втором параграфе (p). Также, мы изменим полученную
информацию и выведем результат на дисплей.
// создание объекта парсера и получение HTML include('simple_html_dom.php'); $html = new simple_html_dom(); $html->load("<html><body><p>Hello World!</p><p>We're here</p></body></html>"); // получение массивов параграфов $element = $html->find("p"); // изменение информации внутри параграфа $element->innertext .= " and we're here to stay."; // вывод echo $html->save();
Как видите реализовать PHP парсинг документа HTML, очень даже просто, используя simple HTML DOM библиотеку.
В принципе, в этом куске PHP кода, все можно понять интуитивно, но если вы в чем-то
сомневаетесь, мы рассмотрим код.
Линия 2-4:
подключаем библиотеку, создаем объект класса и загружаем HTML код из
строки.
Линия 7: С
помощью данной строки, находим все <p> теги в HTML коде,
и сохраняем в переменной в виде массива. Первый параграф будет иметь индекс 0,
остальные параграфы будут индексированы соответственно 1,2,3…
Линия 10:
Получаем содержимое второго параграфа в нашей коллекции. Его индекс будет 1.
Также мы вносим изменения в текст с помощью атрибута innertext. Атрибут innertext, меняет все содержимое внутри
указанного тега. Также мы сможем
изменить сам тег с помощью атрибута outertext.
Давайте добавим еще одну строку PHP кода, с помощью которой мы назначим
класс стиля нашему параграфу.
$element->class = "class_name"; echo $html->save();
Результатом выполнения нашего кода будет следующий HTML документ:
<html> <body> <p>Hello World!</p> <p class="class_name">We're here and we're here to stay.</p> </body> </html>
Другие селекторы
Ниже приведены другие примеры селекторов. Если вы
использовали jQuery, то
в библиотеке simple html dom синтаксис немножко схожий.
// получить первый элемент с id="foo" $single = $html->find('#foo', 0); // получает при парсинге все элементы с классом class="foo" $collection = $html->find('.foo'); // получает все теги <a> при парсинге htmlдокумента $collection = $html->find('a'); // получает все теги <a>, которые помещены в тег <h1> $collection = $html->find('h1 a'); // получает все изображения с title='himom' $collection = $html->find('img');
Использование первого селектора при php парсинге html документа,
очень простое и понятное. Его уникальность в том что он возвращает только один html элемент,
в отличии от других, которые возвращают массив (коллекцию). Вторым параметром (0),
мы указываем, что нам необходим только первый элемент нашей коллекции. Надеюсь,
вам понятны все варианты селекторов библиотеки simple HTML DOM, если вы чего-то не
поняли, попробуйте метод научного эксперимента. Если даже он не помог,
обратитесь в комментарии к статье.
Документация библиотеки
simple HTML DOM
Полнейшую документацию по использованию библиотеки simple HTML DOM вы
сможете найти по этому адресу:
http://simplehtmldom.sourceforge.net/manual.htm
Просто предоставлю вам иллюстрацию, которая показывает
возможные свойства выбранного HTML DOM элемента.
Скрипт Human Emulator парсинга HTML-страницы с использованием XPath
В этой статье мы рассмотрим один из примеров написания скрипта для парсингаHTML-страниц с использованием XPath на примере сайта bing.com.
Сперва определимся с тем, что такое XPath и зачем оно нужно, если есть регулярные выражения?
XPath (XML Path Language) — это язык запросов к элементам XML-подобного документа (далее для краткости просто XML). XPath призван реализовать навигацию по DOM в XML.
Regexp — формальный язык поиска и осуществления манипуляций с подстроками в тексте, основанный на использовании метасимволов. По сути это строка-образец (шаблон), состоящая из символов и метасимволов и задающая правило поиска.
Итак, главная разница в том, что XPath специализируется на XML, а Regexp — на любом виде текста.
В: Зачем использовать XPath, если есть regexp, в котором можно сделать тоже самое?О: Простота поддержки.
Синтаксис у regexp такой, что уже через неделю может быть проще всё переписать, чем вносить изменения, а с XPath можно спокойно работать. И синтаксис у xpath довольно компактный,xml’ё-фобы могут быть спокойны.
Простой пример для вдохновления — получим значение аттрибута «href» у, например, тега «a».
Yohoho! Regexp:
Быстро (несколько небольших страниц) пробежаться по основам XPath можно в туториале от .
Как использовать XPath в PHP можно почитать в документации на . И в небольшом тутораильчике от .
Теперь определимся с необходимым функционалом скрипта:
* Возможность указывать произвольный поисковый запрос
* Парсим только первую страницу поисковой выдачи
* Из поисковой выдачи нам нужно:
* заголовок
* ссылка
* номер в выдаче
Исходя из нашего ТЗ составляем примерный алгоритм работы скрипта:
1) Заходим на bing.com
2) Вводим поисковую фразу
3) Получаем со страницы необходимый результат
Приступим к написанию парсера поисковой выдачи http://bing.com. Для начала, создадим базовый каркас скрипта.
// coding: windows-1251 // Настройка HumanEmulator // ———————————————— // Где запущен XHE $xhe_host = «127.0.0.1:7010»; // HumanEmulator lib require «../../Templates/xweb_human_emulator.php»; // Our tools require «tools/functions.php»; // Настройки скрипта // ———————————————— // Скрипт // ———————————————— // Quit $app->quit();
В настройки добавим переменную для хранения поискового запроса.
// Поисковый запрос $text = «ХуманЭмулятор»;
Заходим на сайт.
// Базовый URL $base_url = «https://www.bing.com/?setlang=en»; $browser->navigate($base_url);
Вводим поисковую фразу.
$input->set_value_by_attribute(«name», «q», true, $text); sleep(1); $element->click_by_attribute(«type», «submit»); sleep(5);
Сохраним в переменную содержимое страницы.
// Получаем содержимое страницы $content = $webpage->get_body();
Настроим xpath-объект:
$dom = new DOMDocument; @$dom->loadHTML($content); $xpath = new DOMXpath($dom);
Теперь у объекта $xpath есть метод «query» в который мы будемпередавать наше xpath-выражение. Давайте начнём создавать xpath-выражение.Открыв исходный код страницы с результатами поисковой выдачи увидим, что сами результаты находятся внутри тега «li».
Т.о. наше xpath-выражение выберет со страницы все поисковые результаты.
$results = $xpath->query(«//li»);
На одной странице у нас должно быть 1 или больше результатов, проверим себя:
if($results === false) { echo «С нашим xpath-выражением что-то не так.» . PHP_EOL; $app->quit(); } elseif($results->length === 0) { echo «Поисковый запрос ‘{$text}’ не принёс результатов.» . PHP_EOL: $app->quit(); } echo «Нашли {$results->length} совпадений.» . PHP_EOL;
Здесь стоит обратить внимание на ветку if, где мы сравниваем кол-во результатов xpath-поиска с нулём. Если наше xpath-выражение ничего не нашло, то это может означать две вещи:* Bing действительно ничего не нашёл
* Bing что-то нашёл, но поменял вёрстку на странице, и наше xpath-выражение необходимо исправлять.
2-й пункт достаточно коварный, в таких случаях, когда xpath-выражение ничего не находит необходимо дополнительно сверятся, чтобы удостоверится, что xpath-выражение не устарело (хотя и это не даст 100% гарантий). В нашем случае будем сверяться с тем, что Bing пишет кол-во найденных результатов.
14 results
А если результатов по поисковому запросу нет, то:
Learn more
— learn about the design goals of the project (features, performance metrics, and more).
— learn how to reference the parser from your project, and how to perform
operations on the AST to answer questions about your code.
— get a more tangible feel for the AST. Get creative — see if you can break it!
— how much of the grammar is supported? Performance? Memory? API stability?
How it works — learn about the architecture, design decisions, and tradeoffs.
Contribute! — learn how to get involved, check out some pointers to educational commits that’ll
help you ramp up on the codebase (even if you’ve never worked on a parser before),
and recommended workflows that make it easier to iterate.
Version 4.4.0 (2020-04-10)
Added
- Added support for passing union types in builders.
- Added end line, token position and file position information for comments.
- Added method to nodes.
Fixed
- Fixed generation of invalid code when using the formatting preserving pretty printer, and
inserting code next to certain nop statements. The formatting is still ugly though. -
no longer requires that the very last comment before a node be a doc comment.
There may not be non-doc comments between the doc comment and the declaration. - Allowed arbitrary expressions in and , rather than just variables.
In particular, this allows , which is legal PHP code.
Истории успешных бизнесменов
Далее будут кратко изложены вдохновляющие биографии четырех ныне живущих, добившихся успеха, всемирно известных деловых людей:
Сергей Брин
Успешный предприниматель, ученый в области вычислительной техники, сооснователь поисковой системы Google, миллиардер. Родился в Москве в небогатой семье ученых-математиков, позже с родителями переехал в США.
Успех пришел к молодому человеку, когда он стал заниматься разработкой поисковой машины (системы) в Стэнфордском университете вместе с Лари Пейджем (в настоящее время также миллиардер).
Придуманную поисковую систему студенты успешно проверили в университете, после чего стали искать инвесторов для дальнейшего развития бизнеса и нашли их. Уже через семь лет имена молодых основателей Google появились в списке миллиардеров журнала Forbes.
Марк Цукерберг
Успешный программист, предприниматель в области интернет-технологий, основатель и разработчик социальной сети Facebook, миллиардер. Родился в небогатой многодетной семье.
Уже в школьные годы увлекался компьютерным программированием и стал называть себя «хакером по призванию». Марк разрабатывал свою социальную сеть вместе с друзьями в Гарварде, финансовую помощь им оказывал студент Эдуардо Северин, позже стали появляться и другие более крупные инвесторы и успех не заставил себя ждать.
Опра Уинфри
Успешная американская телеведущая, актриса, общественный деятель, создавшая свою продюсерскую компанию, а также первая афроамериканка, попавшая в список Forbes, женщина-миллиардер.
Родилась в неблагополучной семье шахтера и горничной. Несмотря на очень тяжелое детство и юность, смогла быстро добиться успеха упорным трудом. Благодаря пробивному характеру и деятельному желанию в 19 лет Опра стала ведущей новостей, позже начала вести ток-шоу. В 32 года она стала миллионером, а в 40 лет – миллиардером. Сегодня Уинфри, помимо всего прочего, успешный медиамагнат, владелица киностудии, журнала, радиосети, кабельного телеканала.
Джоан Роулинг
Британка, чью жизнь до оглушительного успеха нельзя было назвать счастливой, стартовала в бизнесе с абсолютного нуля и стала успешной всемирно известной писательницей благодаря серии романов о Гарри Поттере.
За пять лет Джоан прошла путь от бедности (жила на социальное пособие) до своего первого миллиарда. Сегодня она сценарист, кинопродюсер, наиболее продающийся автор в Великобритании.
Tips
Provide clean input strings
If your input string consists of more than just the name and
directly related bits like salutations, suffixes etc.,
any additional parts can easily confuse the parser.
It is therefore recommended to pre-process any non-clean input
to isolate the name before passing it to the parser.
Multi-pass parsing
We have not played with this, but you may be able to improve results
by chaining several parses in sequence. E.g.
$parser = new Parser(); $name = $parser->parse($input); $name = $parser->parse((string) $name); ...
You can even compose your new input string from individual parts of
a previous pass.
Dealing with names in different languages
The parser is primarily built around the patterns of english names
but tries to be compatible with names in other languages. Problems
occur with different salutations, last name prefixes, suffixes etc.
or in some cases even with the parsing order.
To solve problems with salutations, last name prefixes and suffixes
you can create a separate language definition file and inject it when
instantiating the parser, see ‘Setting Languages’ above and compare
the existing language files as examples.
To deal with parsing order you may want to reformat the input string,
e.g. by simply splitting it into words and reversing their order.
You can even let the parser run over the original string and then over
the reversed string and then pick the best results from either of the
two resulting name objects. E.g. the salutation from the one and the
lastname from the other.
The name parser has no in-built language detection. However, you may
already ask the user for their nationality in the same form. If you
do that you may want to narrow the language definition files passed
into the parser to the given language and maybe a fallback like english.
You can also use this information to prepare the input string as outlined
above.
Alternatively, Patrick Schur as a PHP language detection library
that seems to deliver astonishing results. It won’t give you much luck if
you run it over the the name input string only, but if you have any more
text from the person in their actual language, you could use this to detect
the language and then proceed as above.
Gender detection
Gender detection is outside the scope of this project.
Detecting the gender from a name often requires large lists of first
name to gender mappings.
However, you can use this parser to extract salutation, first name and
nick names from the input string and then use these to implement gender
detection using another package (e.g. this one) or service.
Having fun with normalisation
Writing different language files can not only be useful for parsing,
but you can remap the normalised versions of salutations, prefixes and suffixes
to transform them into something totally different.
E.g. you could map to and then output
the parts in appropriate order to build a pipeline that automatically transforms
e.g. into .
Of course, this is a silly and rather contrived example, but you get the
gist.
Of course this can also be used in more useful ways, e.g. to spell out
abbreviated titles, like as etc. .
Неправильная кодировка при использовании cURL
В настоящее время на большинстве сайтов используется кодировка UTF-8, с которой cURL прекрасно работает.
Но, например, при открытии некоторых сайтов:
curl http://z-oleg.com/
Вместо кириллицы мы увидим крякозяблы:
Кодировку можно преобразовать «на лету» с помощью команды iconv. Но нужно знать, какая кодировка используется на сайте. Для этого обычно достаточно заглянуть в исходный код веб-страницы и найти там строку, содержащую слово charset, например:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Эта строка означает, что используется кодировка windows-1251.
Для преобразования из кодировки windows-1251 в кодировку UTF-8 с помощью iconv команда выглядит так:
iconv -f windows-1251 -t UTF-8
Совместим её с командой curl:
curl http://z-oleg.com/ | iconv -f windows-1251 -t UTF-8
После этого вместо крякозяблов вы увидите русские буквы.
Делаем запросы
Интерфейс класса достаточно простой и прямолинейный. Имена методов соответствуют HTTP-методам, которые он выполняет: GET-метод соответствует методу get(), GET-post(), PUT-put() и т.д. И каждый из этих методов возвращает Promise (если вы знакомы с JavaScript, или ранее работали с ReactPHP, то это не должно вызвать у вас вопросов). Если вы не знаете, что это, то на даном этапе объяснения не имеют большого смысла, дальше будет пример, после которого всё станет понятно.
Для текущей задачи нам будет достаточно одного метода :
В коде выше будет описана анонимная функция, которая после успешного запроса выведет HTML-разметку на экран. Эта функция принимает ответ экземпляра . В этой функции мы можем описать обработчик ответа, который вернёт из этого промиса (Promise) распарсенную информацию, без лишнего HTML-кода.
Как вы можете заметить, алгоритм парсинга достаточно прост:
- Делаем запрос и получаем промис.
- Пишем обработчик этого промиса.
- Парсим нужную информацию внутри этого обработчика.
- Если нужно, повторяем первый шаг.
API Reference
Helper functions
Name | Description |
---|---|
object str_get_html ( string $content ) | Creates a DOM object from a string. |
object file_get_html ( string $filename ) | Creates a DOM object from a file or a URL. |
DOM methods & properties
Name | Description |
---|---|
void __construct ( ) |
Constructor, set the filename parameter will automatically load the contents, either text or file/url. |
string plaintext |
Returns the contents extracted from HTML. |
void clear () |
Clean up memory. |
void load ( string $content ) |
Load contents from a string. |
string save ( ) |
Dumps the internal DOM tree back into a string. If the $filename is set, result string will save to file. |
void load_file ( string $filename ) |
Load contents from a from a file or a URL. |
void set_callback ( string $function_name ) |
Set a callback function. |
mixed find ( string $selector ) |
Find elements by the CSS selector. Returns the Nth element object if index is set, otherwise return an array of object. |
Element methods & properties
Name | Description |
---|---|
string | Read or write element’s attribure value. |
string tag |
Read or write the tag name of element. |
string outertext |
Read or write the outer HTML text of element. |
string innertext |
Read or write the inner HTML text of element. |
string plaintext |
Read or write the plain text of element. |
mixed find ( string $selector ) |
Find children by the CSS selector. Returns the Nth element object if index is set, otherwise, return an array of object. |
DOM traversing
Name | Description |
---|---|
mixed $e->children ( ) |
Returns the Nth child object if index is set, otherwise return an array of children. |
element $e->parent () |
Returns the parent of element. |
element $e->first_child () |
Returns the first child of element, or null if not found. |
element $e->last_child () |
Returns the last child of element, or null if not found. |
element $e->next_sibling () |
Returns the next sibling of element, or null if not found. |
element $e->prev_sibling () |
Returns the previous sibling of element, or null if not found. |