Пишем парсер контента на php
Содержание:
- How to access the HTML element’s attributes?
- Version 4.1.0 (2018-10-10)
- Contributors/Thanks to
- Running Parse Server
- How to find HTML elements?
- Получение в cURL страниц со сжатием
- Version 3.0.3 (2017-02-03)
- Выключаем поворот экрана Пк в настройках графики Intel
- Version 4.0.0-alpha1 (2017-10-18)
- Как парсить сайты
- Motorola Moto G8 Plus
- 5 последних уроков рубрики «PHP»
- Шаг 2 – Основы HTML парсинга
- Скрипт Human Emulator парсинга HTML-страницы с использованием XPath
- Зачем люди пишут парсеры
- Какой способ обработки файлов в PHP является оптимальным?
- Google Фото – лучшее бесплатное хранилище для фото и видео
- 10. Мэрилин Монро
- Неправильная кодировка при использовании cURL
- Делаем запросы
- Извлечение информации из заголовков при использовании cURL
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;
Version 4.1.0 (2018-10-10)
Added
- Added support for PHP 7.3 flexible heredoc/nowdoc strings, completing support for PHP 7.3. There
are two caveats for this feature:- In some rare, pathological cases flexible heredoc/nowdoc strings change the interpretation of
existing doc strings. PHP-Parser will now use the new interpretation. - Flexible heredoc/nowdoc strings require special support from the lexer. Because this is not
available on PHP versions before 7.3, support has to be emulated. This emulation is not perfect
and some cases which we do not expect to occur in practice (such as flexible doc strings being
nested within each other through abuse of variable-variable interpolation syntax) may not be
recognized correctly.
- In some rare, pathological cases flexible heredoc/nowdoc strings change the interpretation of
- Added to to skip both traversal of child
nodes, and prevent subsequent visitors from visiting the current node.
Contributors/Thanks to
- raxbg for contributions to parse , grid lines, and various bugfixes.
- westonruter for bugfixes and improvements.
- FMCorz for many patches and suggestions, for being able to parse comments and IE hacks (in lenient mode).
- Lullabot for a patch that allows to know the line number for each parsed token.
- ju1ius for the specificity parsing code and the ability to expand/compact shorthand properties.
- ossinkine for a 150 time performance boost.
- docteurklein for output formatting and inspiration.
- nicolopignatelli for PSR-0 compatibility.
- diegoembarcadero for keyframe at-rule parsing.
- goetas for @namespace at-rule support.
- View full list
Running Parse Server
Before you start make sure you have installed:
Locally
$ npm install -g parse-server mongodb-runner $ mongodb-runner start $ parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://localhost/test
Note: If installation with fails due to permission problems (),
Inside a Docker container
$ git clone https://github.com/parse-community/parse-server $ cd parse-server $ docker build --tag parse-server . $ docker run --name my-mongo -d mongo
Running the Parse Server Image
$ docker run --name my-parse-server -v config-vol:/parse-server/config -p 1337:1337 --link my-mongo:mongo -d parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://mongo/test
Note:
You can use any arbitrary string as your application id and master key. These will be used by your clients to authenticate with the Parse Server.
That’s it! You are now running a standalone version of Parse Server on your machine.
Using a remote MongoDB? Pass the parameter when starting . Learn more about configuring Parse Server . For a full list of available options, run .
Saving your first object
$ curl -X POST \ -H "X-Parse-Application-Id: APPLICATION_ID" \ -H "Content-Type: application/json" \ -d '{"score":1337,"playerName":"Sean Plott","cheatMode":false}' \ http://localhost:1337/parse/classes/GameScore
You should get a response similar to this:
{ "objectId": "2ntvSpRGIK", "createdAt": "2016-03-11T23:51:48.050Z" }
You can now retrieve this object directly (make sure to replace with the actual you received when the object was created):
$ curl -X GET \ -H "X-Parse-Application-Id: APPLICATION_ID" \ http://localhost:1337/parse/classes/GameScore/2ntvSpRGIK
// Response { "objectId": "2ntvSpRGIK", "score": 1337, "playerName": "Sean Plott", "cheatMode": false, "updatedAt": "2016-03-11T23:51:48.050Z", "createdAt": "2016-03-11T23:51:48.050Z" }
Keeping tracks of individual object ids is not ideal, however. In most cases you will want to run a query over the collection, like so:
$ curl -X GET \ -H "X-Parse-Application-Id: APPLICATION_ID" \ http://localhost:1337/parse/classes/GameScore
// The response will provide all the matching objects within the `results` array: { "results": }
How to find HTML elements?
$ret = $html->find(‘a’);
$ret = $html->find(‘a’, );
$ret = $html->find(‘a’, -1);
$ret = $html->find(‘div’);
$ret = $html->find(‘div’);
$ret = $html->find(‘#foo’);
$ret = $html->find(‘.foo’);
$ret = $html->find(‘*’);
$ret = $html->find(‘a, img’);
$ret = $html->find(‘a, img’);
Supports these operators in attribute selectors:
Filter | Description |
---|---|
Matches elements that have the specified attribute. | |
Matches elements that don’t have the specified attribute. | |
Matches elements that have the specified attribute with a certain value. | |
Matches elements that don’t have the specified attribute with a certain value. | |
Matches elements that have the specified attribute and it starts with a certain value. | |
Matches elements that have the specified attribute and it ends with a certain value. | |
Matches elements that have the specified attribute and it contains a certain value. |
$es = $html->find(‘ul li’);
$es = $html->find(‘div div div’);
$es = $html->find(‘table.hello td’);
$es = $html->find(»table td’);
foreach($html->find(‘ul’) as $ul)
{
foreach($ul->find(‘li’) as $li)
{
}
}
$e = $html->find(‘ul’, )->find(‘li’, );
Получение в cURL страниц со сжатием
Иногда при использовании cURL появляется предупреждение:
Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.
Его можно увидеть, например при попытке получить страницу с kali.org,
curl https://www.kali.org/
Суть сообщения в том, что команда curl выведет бинарные данные, которые могут навести бардак в терминале
Нам предлагают использовать опцию «—output -» (обратите внимание на дефис после слова output – он означает стандартный вывод, т.е. показ бинарных данных в терминале), либо сохранить вывод в файл следующим образом: «—output «.
Причина в том, что веб-страница передаётся с использованием компрессии (сжатия), чтобы увидеть данные достаточно использовать опцию —compressed:
curl --compressed https://www.kali.org/
В результате будет выведен обычный HTML код запрашиваемой страницы.
Version 3.0.3 (2017-02-03)
Fixed
- In the is now parsed as an rather than . (#325)
- Ensure integers and floats are always pretty printed preserving semantics, even if the particular
value can only be manually constructed. - Throw a when trying to pretty-print an node. Previously this resulted in
an undefined method exception or fatal error.
Added
- Added support for negative interpolated offsets:
- Added option to . If this option is enabled, an
attribute, containing the unresolved name, will be added to each resolved name. - Added option, which dumps nodes with position information.
Deprecated
The XML serializer has been deprecated. In particular, the classes Serializer\XML,
Unserializer\XML, as well as the interfaces Serializer and Unserializer are deprecated.
Выключаем поворот экрана Пк в настройках графики Intel
Восстановить оригинальную ориентацию экрана можно также через центр управления видеоадаптером. Интерфейс панели управления может отличаться от представленной далее, но алгоритм работы остается одинаковый.
В правой части панели управления следует найти раздел «Дисплей». Далее выбрать подпункт «Поворот дисплея», а в нем вид ориентации. Чтобы вернуть стандартный режим отображения изображений достаточно указать вариант «альбомная».
На ПК с видеокартой AMD процесс обстоит иначе. В центре управления нужно выбрать пункт «Общие задачи», а затем «Повернуть рабочий стол». На экране отобразятся сообщения с требуемым вариантом поворота. Пользователю остается выбрать подходящий.
Повернуть экран ноутбука можно через адаптер Intel. Ярлык расположен в трее. Щелкаем ЛКМ по ярлыку и выбираем пункт «Графические характеристики».
В разделе «Основные настройки» области «Поворот» выбираем вариант отображения изображения и жмем ОК.
Version 4.0.0-alpha1 (2017-10-18)
Added
- Added experimental support for format-preserving pretty-printing. In this mode formatting will be
preserved for parts of the code which have not been modified. - Added option to , defaulting to true. If this option is disabled,
resolved names will be added as attributes, instead of replacing the original
names. - Added class, which can be used to find nodes based on a callback or class name. This
is a utility to avoid custom node visitor implementations for simple search operations. - Added method.
- Added methods: method for creating an AST for a simple value,
for creating concatenation trees, for preparing function arguments. - Added class, which encapsulates the logic independently of the actual
AST traversal. This facilitates use in other context, such as class names in doc comments.
Additionally it provides an API for getting the shortest representation of a name. - Added method.
- Added . This allows conversion JSON back into an AST.
- Added methods and .
- Added and nodes, which are used in place of simple strings in
many places. - Added , , , , ,
and methods to . These provide a more obvious access
point for the already existing attributes of the same name. - Added to evaluate constant expressions to PHP values.
- Added , returning for , etc.
Changed
- Many subnodes that previously held simple strings now use (or )
nodes. Please see the UPGRADE-4.0 file for an exhaustive list of affected nodes and some notes on
possible impact. - Expression statements () are now represented using a node. Previously
these statements were directly represented as their constituent expression. - The subnode of has been renamed to and now contains a rather than
a plain string. - The subnode of has been renamed to and now contains a rather
than a plain string. - The subnode of now contains a rather than a plain string.
- The subnode of now contains a rather than a plain string.
- The subnode of is now if no explicit alias is given. As such,
and are now represented differently. The method
can be used to get the effective alias, even if it is not explicitly given.
Removed
- Support for running on PHP 5 and HHVM has been removed. You can however still parse code of old
PHP versions (such as PHP 5.2), while running on PHP 7. - Removed subnode on , and nodes. Use instead.
- The method has been removed. Constants cannot have a static modifier.
- The no longer accepts as a return value from a method.
should be returned instead. - The method has been removed. If you really need to, you can use
instead. - The misspelled constant has been dropped in favor of
. - The XML serializer has been removed. As such, the classes , and
, as well as the interfaces and no longer exist. - The class has been removed. It’s functionality is moved into .
However, this is an internal class and should not be used directly.
Как парсить сайты
Я долго не хотел писать эту статью, поскольку конкретного смысла в ней нет. Чтобы сделать парсер на PHP, нужно знать этот язык. А те, кто его знает, такой вопрос просто не зададут. Но в этой статье я расскажу, как вообще создаются парсеры, а также, что конкретно нужно изучать.
Итак, вот список пунктов, которые необходимо пройти, чтобы создать парсер контента на PHP:
- Получить содержимое страницы и записать его в строковую переменную. Наиболее простой вариант — это функция file_get_contents(). Если контент доступен только авторизованным пользователям, то тут всё несколько сложнее. Здесь уже надо посмотреть, каков механизм авторизации. Далее, используя cURL, отправить правильный запрос на форму авторизации, получить ответ и затем отправить правильные заголовки (например, полученный идентификатор сессии), а также в этом же запросе обратиться к той странице, которая нужна. Тогда уже в этом ответе Вы получите конечную страницу.
- Изучить структуру страницы. Вам нужно найти контент, который Вам необходим и посмотреть, в каком блоке он находится. Если блок, в котором он находится не уникален, то найти другие общие признаки, по которым Вы однозначно сможете сказать, что если строка удовлетворяет им, то это то, что Вам и нужно.
- Используя строковые функции, достать из исходной строки нужный Вам контент по признакам, найденным во 2-ом пункте.
Отмечу так же, что всё это поймёт и сможет применить на практике только тот, кто знает PHP. Поэтому те, кто его только начинает изучать, Вам потребуются следующие знания:
- Строковые функции.
- Библиотека cURL, либо её аналог.
- Отличное знание HTML.
Те же, кто ещё вообще не знает PHP, то до парсеров в этом случае ещё далеко, и нужно изучать всю базу. В этом Вам поможет мой курс, либо какие-нибудь книги по PHP.
Безусловно, Америки я в этой статье не открыл, но слишком много вопросов по теме парсеров, поэтому этой статьёй я постарался лишь дать развёрнутый ответ.
Motorola Moto G8 Plus
-
Дисплей: 6,3 дюйма, FHD+, IPS
-
Процессор: Snapdragon 665
-
Память: 4/64 Гб
-
ЦАП: отсутствует
-
Батарея: 4000 мАч
Цена: от 16 000 руб.
Бюджетные смартфоны довольно редко оснащаются стереодинамиками, но модель от Motorola в этом плане стала приятным исключением. Аппарат имеет действительно качественное звучание. Смотреть на нем фильмы или слушать музыку без наушников вполне комфортно. На этом фишки модели не закончились – есть защита от брызг P2i, NFC, разъем 3,5 и тройная камера 48+5+16 Мп. Фронтальная камера – 25 Мп.
Достоинства:
-
Быстрая зарядка.
-
Качественная фотокамера и интересные режимы для съемки.
-
Есть NFC.
-
Приятное звучание.
-
Защита от брызг.
-
Неплохая производительность.
Недостатки:
-
Смартфоны Motorola всегда внешне отличались от конкурентов, G8 Plus – это типичный девайс с Андроид без ярко-выраженных особенностей.
-
Комбинированный слот.
-
Маркий корпус.
5 последних уроков рубрики «PHP»
Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.
Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак
В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.
Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение
В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.
Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.
Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.
Шаг 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
А если результатов по поисковому запросу нет, то:
Зачем люди пишут парсеры
Немного отклонившися от курса этой статьи, на живом примере расскажу, где из популярных сайтов используется регулярный парсинг и наполнение с другого более популярного сайта.
Существует один сайт, уверен, на который вы натыкались в гугле при поиске решений проблем при программировании — qaru.site. И идея этого сайта как раз и строится на основу двух парсеров. Первый из которых копирует вопросы со всей информацией с популярного англоязычного сайта-аналога stackoverflow.com. А задача второго — переводить текст вопроса и ответов с английского на русский (с первого взгляда кажется, что это производится через Google Translate).
То, есть, если рассматривать роль парсера в проекте qaru.site, то, без раздумий можно утверждать то, что парсер в этом проекте — это 80% его успеха. Ведь, вместо того, чтобы развивать свой форум с нуля, просто было скопировано большое количество реальной информации с другого сайта. И из-за того, что эта информация в оригинале была на английском, то, со стороны поисковых систем её перевод расценивается как условно-полностью уникальный текст (невзирая на то, что перевод постов там сродни «я твой дом труба шатать»).
Но, это только один пример, придуманный сходу. На самом же деле, парсеры используются почти в каждом проекте: для наполнения сайта данными, для актуализации и обновления. Потому, их применение достаточно широко, и интересно. Потому знать, как писать парсер на php нужно. А если вы ещё освоите многопоточный парсинг, то жизнь станет ещё проще ^^.
Какой способ обработки файлов в PHP является оптимальным?
Сами по себе PHP функции чтения файлов достаточно шустрые, поэтому, чтобы добиться хоть каких-то более-менее осязаемых цифр времени их работы, я специально оставил в тестируемых фрагментах операции с базой данных, которые во всех случаях были одни и те же.
Время работы PHP скрипта я также решил для удобства округлять до третьего знака после запятой, т.е. до тысячных долей секунд (хотя, можно было ограничиться и сотыми, на самом деле).
Помню, когда я учился в школе и писал свою научную работу по физике (да, был такой опыт ) на её защите перед университетскими преподавателями меня постоянно упрекали за недостаточное количество экспериментов (я делал по 3 опыта для каждого случая). «Светилы науки» называли цифры в 100, ну или, хотя бы, в 10 экспериментов для сравнения различных ситуаций, чтобы можно было делать какое-то их сопоставление и минимизировать вероятность случайного превосходства одного над другим.
Да, досталось мне тогда от них крепко, но их рекомендации я хорошо усвоил, что даже сейчас об этом помню, хотя прошло уже более 10 лет с тех пор. Тем более, что данные рекомендации действительно были основаны на законах математической статистики и теории вероятности.
Ну, на научность своих нынешних экспериментов я в данной статье не претендую, поэтому число в 100 экспериментов я посчитал излишне большим, а процесс их проведения — слишком утомительным занятием.
В итоге, я решил ограничиться 10 экспериментами для каждого варианта PHP парсера файла, чего, как оказалось в итоге, оказалось вполне достаточно, чтобы выделить явного лидера без всякой подтасовки фактов и зацепок за сотые и тысячные доли секунды превосходства.
Результаты вычислений времени работы разработанных мною PHP парсеров файла представлены в следующей таблице и рассортированы по PHP функциям, на базе которых они работают.
Эксперимент | fgets() | file() | fread() | file_get_contents() |
1 | 9,147 | 9,722 | 10,539 | 2,008 |
2 | 8,950 | 9,006 | 9,495 | 1,733 |
3 | 8,821 | 8,845 | 9,207 | 1,642 |
4 | 8,717 | 8,876 | 8,931 | 1,758 |
5 | 9,010 | 9,091 | 8,703 | 1,635 |
6 | 9,110 | 8,640 | 9,712 | 1,633 |
7 | 9,074 | 9,626 | 9,13 | 1,645 |
8 | 8,886 | 9,204 | 9,048 | 1,701 |
9 | 8,667 | 8,918 | 9,438 | 1,713 |
10 | 8,852 | 9,197 | 9,537 | 1,567 |
Среднее | 8,923 | 9,113 | 9,374 | 1,704 |
Как видите, помимо значений времени выполнения скрипта в каждом из 10 экспериментов, я решил подсчитать среднюю температуру по больнице
А именно, арифметическое среднее время работы каждого PHP парсера файла, чтобы можно было выявить лидера.
И им оказался, как видите, последний вариант, реализованный на базе функции file_get_contents(), который выполняет чтение содержимого файла в строковую переменную с дальнейшим его преобразованием в массив и обработкой в цикле.
Все остальные варианты PHP парсеров файлов работают примерно с одинаковой скоростью.
Почему именно он обогнал своих конкурентов я, если честно, не имею ни малейшего понятия. Могу лишь предположить, что операция чтения файла в строку с помощью file_get_contents() требует меньше ресурсов, чем формирование готового массива строк с помощью file().
А превосходство над fgets() и fread() можно списать на то, что перед их использованием требуется открытие файла с помощью fopen(), на что требуется время.
Да, на самом деле, это и не важно, т.к. цифры говорят сами за себя: благодаря использованию функции file_get_contents() PHP парсер файла на его базе работает в 5 раз быстрее остальных, что и повлияло на моё решение использовать его на практике
Google Фото – лучшее бесплатное хранилище для фото и видео
10. Мэрилин Монро
Неправильная кодировка при использовании 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-кода.
Как вы можете заметить, алгоритм парсинга достаточно прост:
- Делаем запрос и получаем промис.
- Пишем обработчик этого промиса.
- Парсим нужную информацию внутри этого обработчика.
- Если нужно, повторяем первый шаг.
Извлечение информации из заголовков при использовании cURL
Иногда необходимо извлечь информацию из заголовка, либо просто узнать, куда делается перенаправление.
Заголовки – это некоторая техническая информация, которой обмениваются клиент (веб-браузер или программа curl) с веб-приложением (веб-сервером). Обычно нам не видна эта информация, она включает в себя такие данные как кукиз, перенаправления (редиректы), данные о User Agent, кодировка, наличие сжатия, информация о рукопожатии при использовании HTTPS, версия HTTP и т.д.
Пример команды:
curl -s -I -A 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36' https://www.acrylicwifi.com/AcrylicWifi/UpdateCheckerFree.php?download | grep -i '^location'
Получаемый результат:
location: https://tarlogiccdn.s3.amazonaws.com/AcrylicWiFi/Home/Acrylic_WiFi_Home_v3.3.6569.32648-Setup.exe
В этой команде имеются уже знакомые нам опции -s (подавление вывода) и -A (для указания своего пользовательского агента).
Новой опцией является -I, которая означает показывать только заголовки. Т.е. не будет показываться HTML код, поскольку он нам не нужен.
На этом скриншоте видно, в какой именно момент отправляется информация о новой ссылке для перехода:
curl -s -v http://www.paterva.com/web7/downloadPaths41.php -d 'fileType=exe&os=Windows' 2>&1 | grep -i 'Location:'
Обратите внимание, что в этой команде не использовалась опция -I, поскольку она вызывает ошибку:
Warning: You can only select one HTTP request method! You asked for both POST Warning: (-d, --data) and HEAD (-I, --head).
Суть ошибки в том, что можно выбрать только один метод запроса HTTP, а используются сразу два: POST и HEAD.
Кстати, опция -d (её псевдоним упоминался выше (—data), когда мы говорили про HTML аутентификацию через формы на веб-сайтах), передаёт данные методом POST, т.е. будто бы нажали на кнопку «Отправить» на веб-странице.
В последней команде используется новая для нас опция -v, которая увеличивает вербальность, т.е. количество показываемой информации. Но особенностью опции -v является то, что она дополнительные сведения (заголовки и прочее) выводит не в стандартный вывод (stdout), а в стандартный вывод ошибок (stderr). Хотя в консоли всё это выглядит одинаково, но команда grep перестаёт анализировать заголовки (как это происходит в случае с -I, которая выводит заголовки в стандартный вывод). В этом можно убедиться используя предыдущую команду без 2>&1:
curl -s -v http://www.paterva.com/web7/downloadPaths41.php -d 'fileType=exe&os=Windows' | grep -i 'Location:'
Строка с Location никогда не будет найдена, хотя на экране она явно присутствует.
Конструкция 2>&1 перенаправляет стандартный вывод ошибок в стандартный вывод, в результате внешне ничего не меняется, но теперь grep может обрабатывать эти строки.
Более сложная команда для предыдущего обработчика форм (попробуйте в ней разобраться самостоятельно):
timeout 10 curl -s -L -v http://www.paterva.com/web7/downloadPaths.php -d 'fileType=exe&client=ce&os=Windows' -e 'www.paterva.com/web7/downloads.php' 2>&1 >/dev/null | grep -E 'Location:'