06 December 2024
Як використовувати все це добро, багато написано в Мережі, тому зупинюся на практичних моментах "експлуатації" (стаття написана спеціально для dkws.org.ua)
Уявимо, що у нас є сайт, на який потрібно з XML видерти деяку інформацію (припустимо з стрічки новин або ще з чого-небудь). Нехай є шлях самого RSS/XML:
$patha = "https://www.vcerecepti.com/i/%D1%81%D0%B0%D0%BB%D0%B0%D1%82.html?rss=1"
Код буде приблизно таким:
// для нормальної роботи з UTF-8 mb_Internal_Encoding ( 'UTF-8'); // Створюємо новий документ $xmlDoc = новий DOMDocument(); // Завантажуємо посилання (написано для dkws.org.ua) $xmlDoc->load($patha); // Отримуємо елементи з "channel" $channel=$xmlDoc->getElementsByTagName('channel')->item(0); $channel_title = $channel->getElementsByTagName('title') ->item(0)->childNodes->item(0)->nodeValue; $channel_link = $channel->getElementsByTagName('link') ->item(0)->childNodes->item(0)->nodeValue; $channel_desc = $channel->getElementsByTagName('description') ->item(0)->childNodes->item(0)->nodeValue; // Виводимо елементи з "channel" // Загалом, наступний аналіз мало цікавий, оскільки про це і так написано в мережі
Все працює чудово, поки не з'являється підлий амперсанд в URL, наприклад:
$patha = "https://www.vcerecepti.com/i/%D1%81%D0%B0%D0%BB%D0%B0%D1%82.html?rss=1&p=2";
З'явиться помилка EntityRef: expecting ';' in ім'я_RSS
Якщо вам пощастить, то & можна просто замінити на &
Але може бути варіант гірший, коли американці є в самому XML-коді. У цьому випадку їх також потрібно замінити на &. Є два способи. Перший - це отримати XML-код за допомогою file_get_contents() або будь-яким іншим способом, наприклад, за допомогою curl, закачавши на сервері, а потім прочитавши його в змінну. Після того функцією str_replace змінюємо & & та отриманий XML-код передаємо в клас методом loadXML():
$xmlDoc->loadXML($xml);
Але тут виникають проблеми продуктивності. DOMDocument і так не дуже швидкий, а якщо ще й проводити всі ці маніпуляції з курлом та заміною амперсандів, то нетерплячі користувачі можуть не дочекатися виведення сторінки. Тому виникла думка кешування. Створюється окремий сценарій, який запускається, скажімо, раз на добу кроном і проходить по всіх сторінках RSS, тобто:
https://www.vcerecepti.com/i/%D1%81%D0%B0%D0%BB%D0%B0%D1%82.html?rss=1
https://www.vcerecepti.com/i/%D1%81%D0%B0%D0%BB%D0%B0%D1%82.html?rss=1&p=2
https://www.vcerecepti.com/i/%D1%81%D0%B0%D0%BB%D0%B0%D1%82.html?rss=1&p=3
https://www.vcerecepti.com/i/%D1%81%D0%B0%D0%BB%D0%B0%D1%82.html?rss=1&p=4
і т.д.
Кожну сторінку він зберігає у файлі, наприклад, rep1.xml, rep2.xml, rep3.xml і т.д. У цих файлах він замінює амперсанди на потрібну послідовність символів. А наш основний сценарій (Деніс Колнісниченко, dkws. org. ua) працює не з віддаленим RSS/XML, а завантажує методом load() створені раніше "правильні" XML-файли: rep1.xml, rep2.xml і т.д. - Залежно від переданої йому змінної $ p.
По-перше, ми суттєво прискорюємо сценарій, тому що не потрібно завантажувати XML з віддаленого сервера, а ми завантажуватимемо його з локального диска.
По-друге, ми позбавляємося ситуації, коли віддалений сервер "завис", з ним немає зв'язку або сталася ще якась оказія. В цьому випадку наш основний сценарій просто не відкрився б, тому що не зміг би отримати XML. А так XML під боком. Навіть якщо з віддаленим сервером щось і станеться, сценарій просто використовуватиме старий варіант, створений день тому.
Є недолік. Якщо сторінок багато і вони більші можна перевищити максимальний час виконання. У цьому випадку потрібно розбити сценарій на 3-4, кожен з яких отримуватиме свою порцію XML. Наприклад, перший обробляє перші 15 сторінок, другий – наступні 15 сторінок тощо. Всі ці сценарії, щоб не було зайвого навантаження на сервер, потрібно запускати з інтервалом в 5 - 10 хвилин. Також потрібно враховувати звичайний час оновлення ресурсу, з якого здирається XML (створено для dkws.org.ua): якщо він оновлюється о 7-й ранку, то запускати наші сценарії потрібно, починаючи з 7:20, щоб вони отримали не вчорашній XML, а свіжий .
Зразковий код отримання та приводу до почуття XML-коду для однієї сторінки:
// Шлях до XML $ ch = curl_init ($ patha); // Відкриваємо файл rep2.xml $fp = fopen("rep2.xml", "w"); curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); // Отримуємо та зберігаємо файл curl_exec($ch); curl_close($ch); fclose($fp); // Заміна у файлі $file = fopen('rep.xml', 'r'); $text = fread($file, filesize('rep2.xml')); fclose($file); $file = fopen('rep.xml', 'w'); fwrite($file, str_replace('&p', '&p', $text)); fclose($file);
На цьому все. Успіхів!