Хабрастатистика
Собственно после появления довольно интересного и популярного топика Хабракамп товарищ opium создал вопрос, где предложил создать скрипт статистики.
Несмотря на работу, личную жизни и другие факторы, которые затянули создание скрипта, я все-таки его допилил до какой-то кондиции.
Также я столкнулся с проблемами, которые раньше еще не видал.
Полезный опыт, как никак.
Проблема первая
Изначально, увидев топик, я захотел клиентский скрипт, т.е. на языке javascript.
Но тут меня ожидала бритва в виде политики безопасности, поэтому все мои попытки ajax-запросов и iframe успехом не увенчались. Я подсознательно понимал, что на js какая-нибудь бяка, да будет.
Проблема вторая, хитрая
Думаю, ну и ладно, буду писать на PHP (хотя очень хотелось написать на Python, который я изучаю потихоньку, но это бы затянулось надолго). Продумал детали, начал писать код.
Я получил рейтинги комментов первого уровня используя средства DOM. В моей голове вертятся мысли «надо привести их к integer». Понимаю, что есть значения 0, значения с плюсом и минусом. Минус пусть будет, плюс отрезаю, кастую файрболл в integer, смотрю что вышло через print_r. Я знал, что должен встретить рейтинг -34, но его там не было! Я впал в такой ступор, что решил пойти немного прогуляться и развеять закипевшие от удивления
Долго рассказывать, как я искал баг, скажу сразу: проблема была в знаке минус, который почему-то шел закодированно как-то. Фикс выглядит как костыль; очень надеюсь что есть на хабре люди, которые знают грамотное решение проблемы (попрошу заметить, что на stackoverflow и php manual я ответа не нашел, может искал плохо?):
/**
* Here is awesome "-"
* Parsed num is -34
* var_dump($num); string(5) "–34"
* TODO: FIX THIS UTF-8 SHIT
*/
if (strlen($int) !== strlen($num)) {
preg_match('/d+/', $num, $m);
$int = intval('-' . $m[0]);
}
Немного полезной информации
libxml errors
При загрузке данных в объект DOMDocument у меня плохо парсились entities и естественно я получал E_WARNING. Хорошо, что это не первый опыт работы с DOM, поэтому обернул
libxml_use_internal_errors(true);
$dom->loadHTML('html content');
libxml_clear_errors();
Описывать функции не буду, все отлично указано в документации.
По хорошему надо по новой вызвать libxml_use_internal_errors с указав параметр false, но т.к. больше парсить мне ничего не надо, то я решил опустить этот момент.
DOMXpath
Как можно было догадаться, в бой вступил класс DOMXPath, который упрощает работу по поиску нужных элементов в документе.
Я понимал, что корневой элемент у меня div#comments, поэтому сохранил его для дальнейшего использования. А сам запрос xpath инкапсулировал.
DOMXPath->query возвращает DOMNodeList. Я добавил DOMElement[], чтобы сохранить автокомплит для IDE во время переборал результата в цикле foreach.
Плюс я добавил возможность указания кастомного контекста, который может понадобиться в будущем. Я сейчас думаю, как реализовать подсчет ответов на вопросы (да что скрывать, алгоритм сбора вопросов тоже надо исправить, чтобы рекурсивно прошелся по дереву комментариев), и понимаю, что тут контекст запроса будет как раз кстати.
/**
* Execute xpath query
*
* @param string $query XPath query
* @param DOMNode $context [Optional] Context
* @return DOMNodeList|DOMElement[]
*/
private function query($query, DOMNode $context = null) {
if ($context === null) {
$context = $this->context;
}
return $this->xpath->query($query, $context);
}
FINISH HIM
Ссылка на проект:
github.com/miraage/habrastats
Для локальных тестов я сохранил файлик habratopic.htm, чтобы не ждать каждый раз загрузки топика.
Топик по умолчанию — Хабракамп. Можно передать через habrastats.php?id=XXXX
Хостить в данный момент демо негде.
The End
Буду рад Вашим комментариям, замечаниям, конструктивной критике и пулл реквестам.
P.S.
Если все-таки решите делать пулл реквест, то делайте его из отдельной feature ветки.
В этой статье довольно понятно описывается работа с ветками в git.
Автор: Miraage