- PHP Get Contents of a URL or Page
- 6 Answers 6
- Как получить контент веб-страницы, если по ссылке с именем хоста не получилось
- 1. Парсер для получения контента по ссылкам
- 2. Попытка решения в лоб за счет «имитации» браузера доп. заголовками в запросе
- 2.1. Заголовок с Host
- 3. Изучение веб-страницы, «проблемной» для парсера
- 4. ПО для сбора контента с веб-сайтов
- 5. Возврат к мысли про ссылку с IP-адресом сервера
- 6. Выводы и решение
- How to read a web page in PHP?
- 3 Answers 3
- Как получить содержимое страницы, которая грузится через AJAX?
- 5 ответов 5
PHP Get Contents of a URL or Page
I am trying to create a PHP script which can request data, such as HTML content, from an external server, then do something with the received content. Here is a generalized example of what I am trying to accomplish:
//Get the HTML generated by http://api.somesite.com/ //Now tack on the Unix timestamp of when the data was received $myFetchedData = $dataFromExternalServer . "\n Data received at: ". time(); echo $myFetchedData;
I’m thinking I should use curl in here somewhere, but I am not sure after that. Could someone post a generalized example of how I could do this?
6 Answers 6
If you only need GET and allow_url_fopen is enabled on your server, you can simply use
$data = file_get_contents('http://api.somesite.com');
Yes, I just need a simple GET request. I know allow_url_fopen isn’t enabled by default on some web-hosts, especially on the budget hosts. To allow maximum compatibility, which do you recommend, file_get_contents() or the curl library?
This is how you would use cURL to get contents from a remote url. You would define the function and make calls like url_get_contents(«http://example.com/»);
function url_get_contents($url, $useragent='cURL', $headers=false, $follow_redirects=true, $debug=false) < // initialise the CURL library $ch = curl_init(); // specify the URL to be retrieved curl_setopt($ch, CURLOPT_URL,$url); // we want to get the contents of the URL and store it in a variable curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // specify the useragent: this is a required courtesy to site owners curl_setopt($ch, CURLOPT_USERAGENT, $useragent); // ignore SSL errors curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // return headers as requested if ($headers==true)< curl_setopt($ch, CURLOPT_HEADER,1); >// only return headers if ($headers=='headers only') < curl_setopt($ch, CURLOPT_NOBODY ,1); >// follow redirects - note this is disabled by default in most PHP installs from 4.4.4 up if ($follow_redirects==true) < curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); >// if debugging, return an array with CURL's debug info and the URL contents if ($debug==true) < $result['contents']=curl_exec($ch); $result['info']=curl_getinfo($ch); >// otherwise just return the contents as a variable else $result=curl_exec($ch); // free resources curl_close($ch); // send back the data return $result; >
Как получить контент веб-страницы, если по ссылке с именем хоста не получилось
Простым языком об использовании PHP с cURL на одном примере сайта с JavaScript-защитой.
1. Парсер для получения контента по ссылкам
Задача парсера тривиальная — агрегатор новостей: сбор контента с новостных сайтов.
На входе: файл с URL-ссылками на статьи для сбора.
Веб-интерфейс для администратора: php-страница с кнопкой для запуска скрипта парсера.
Скрипт: использование cURL — с минимальным набором опций.
function cURL_get_content($url)
- заходит на страницу запуска скрипта,
- нажимает кнопку запуска. 2) Скрипт:
- обходит (в цикле) массив ссылок на сайты,
- собирает контент статей,
- формирует веб-страницы по заданному шаблону.
Проблема: наткнувшись на интересную статью с сайта о недвижимости (Домофонд), попытался добавить ее в файл ссылок для сбора контента.
Контент со страницы не собрался: 403 Forbidden.
Спойлер: если сразу интересно найденное решение, то можно переходить к заключению, пропустив бесплодные попытки поиска.
2. Попытка решения в лоб за счет «имитации» браузера доп. заголовками в запросе
В поисках сначала натолкнулся на статьи о том, что некоторые сайты ставят защиту от ботов (чем и является парсер для сбора контента). Например, при использовании cURL надо «оживлять» запрос заголовками, что я и делал, но безуспешно — проиллюстрирую одной из попыток.
function cURL_get_content($url)< $url_1 = "https://www.domofond.ru/"; $url_2 = $url; $headers = array( 'GET ' . $url_2 . ' HTTP/1.1', "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Accept-Encoding: gzip, deflate", "Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7", "Host: domofond.ru", "Referer: domofond.ru", "Upgrade-Insecure-Requests: 1", 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36', 'Cookie: dfuid=5e0dd723-40e6-46cf-a2f1-1db784e320e1; _ga=GA1.2.140590976.1641893876; rrpvid=42725831313485; rcuid=6166ad1a101fb8000139a8a9; _ym_uid=1641893879540019262; _ym_d=1641893879; __gads=ID=00752b7382f51452:T=1641893879:S=ALNI_ManEsFfeviPUR29VUUnBx_DcgsAxQ; _gid=GA1.2.589118605.1642400326; _ym_visorc=w; _ym_isad=2; cto_bundle=ellcGV9VT0c4Q0Vrd2E3dEhtVmhJNk1Ic20xaHNnNXhuSiUyRiUyQiUyRnZYMlFEV0tnNExTWmhQUjJJVzdUOHdkNmlKdnh1aEZtUWMzQ0dxV25Nb3hrYktOeUpEMjZLZ0xLTFElMkZDekxiSkh6elEyOFM0UHVZZ2xHTklpQ2RJOTRkb1Q3QUNTODRlR0hnU0Z1MEFkeDBtNTc1MVozdjVndyUzRCUzRA' ); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); . >
Пример запроса с заголовками:
GET /statya/kolichestvo_dolgostroev_uvelichilos_v_vosemnadtsati_regionah_rf_za_2021_god/102082 HTTP/1.1 Host: www.domofond.ru User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36 Accept: . +куки +смотрел/добавлял заголовки, отправленные в браузере
2.1. Заголовок с Host
Хотя при добавлении хост-заголовка все же возникла одна из мыслей.
Если значение заголовка менялось с «Host: www.domofond.ru» на «Host: domofond.ru» (без www.), то появлялась ошибка: 421 Misdirected Request.
Поэтому в браузере я вручную открывал страницу с/без www — естественно, визуально для меня ничего не менялось.
Перенаправление срабатывало нормально, но потом я еще решил изменить и протокол, чтобы проверить, какой будет редирект.
Сменив в браузере ссылку с https:// на http:// (с/без www) получал нормальный редирект на главное зеркало (https://www.) с нормальным отображением статьи.
При этом вместо статьи отобразилась та же ошибка: 421 Misdirected Request.
3. Изучение веб-страницы, «проблемной» для парсера
Продолжив поиски по теме защиты на сайтах от ботов, столкнулся с выполнением JavaScript-кода на страницах для этой цели.
Сразу скажу, что в браузере отключил выполнение JavaScript-сценариев, но страница продолжила отображаться нормально.
Хотя при изучении кода проблемной страницы смутил следующий скрипт, включающий в виде JSON-блока контент статьи.
4. ПО для сбора контента с веб-сайтов
В ходе исследований попадались статьи на «безголовые» браузеры, среды наподобие селениума и т.п.
Предлагалась имитация действий пользователя, установка тайм-аутов при обращении к сайту для снижения нагрузки и т.д.
Но для решения задач по парсингу одной-двух ссылок, а не многопоточного скачивания всего сайта это не подходило.
Глубоко в этом направлении не разбирался и не копал.
5. Возврат к мысли про ссылку с IP-адресом сервера
Пришлось вернуться к начальному вопросу: как получить контент веб-страницы, если по ссылке с именем хоста не получилось.
В ответ получил содержимое страницы.
6. Выводы и решение
В чем проблема — до конца непонятно. Закроет ли собственник сайта (Домофонд) эту дыру и сможет ли это вообще сделать — неясно.
Но в статье приведено достаточно простое решение и оно работает, а на просторах интернета с такой легкой подсказкой я не сталкивался.
В решении дополнил скрипт методом gethostbyname, чтобы получать IPv4-адрес, соответствующий переданному имени хоста.
Парсер для получения контента по ссылке на входе имеет тот же набор URL-ссылок, но теперь обращается по IP-адресам серверов, что не мешает его работе в сборе данных.
How to read a web page in PHP?
I’m trying to save some web pages to text files using PHP scripts. How can I load a web page into a file buffer with PHP and remove HTML tags?
3 Answers 3
$url = "http://www.brothersoft.com/publisher/xtracomponents.html"; $page = file_get_contents($url); $outfile = "xtracomponents.html"; file_put_contents($outfile, $page);
The code above is just an example and lacks any(!) error checking and handling.
As the other answers have said, either standard PHP stream functions or cURL is your best bet for retrieving the HTML. As for removing the tags, here are a couple approaches:
Option #1: Use the Tidy extension, if available on your server, to walk through the document tree recursively and return the text from the nodes. Something like this:
function textFromHtml(TidyNode $node) < if ($node->isText()) < return $node->value; > else if ($node->hasChildren()) < $childText = ''; foreach ($node->child as $child) $childText .= textFromHtml($child); return $childText; > return ''; >
You might want something more sophisticated than that, e.g., that replaces
tags (where $node->name == ‘br’ ) with newlines, but this will do for a start.
Then, load the text of the HTML into a Tidy object and call your function on the body node. If you have the contents in a string, use:
$tidy = new tidy(); $tidy->parseString($contents); $text = textFromHtml($tidy->body());
Option #2: Use regexes to strip everything between < and >. You could (and probably should) develop a more sophisticated regex that, for example, matched only valid HTML start or end tags. Any errors in the synax of the page, like a stray angle bracket in body text, could mean garbage output if you aren’t careful. This is why Tidy is so nice (it is specifically designed to clean up bad pages), but it might not be available.
Как получить содержимое страницы, которая грузится через AJAX?
Получить содержимое страницы на PHP. Раньше я делал это достаточно легко через file_get_contents( $url ). Но на одном сайте список товаров грузится ajax-om, точнее ангуляром.
То есть если открыть такую страницу в браузере, у вас будет крутиться лоадер и через некоторе время появятся товары. Функция file_get_contents( $url ) получает сырой код, то есть типа
5 ответов 5
Вам может помочь phantomjs. Через метод evaluate вы получите контекст загруженной страницы, а дальше можете либо качать всю страницу, либо весь арсенал JS селекторов у вас в руках. Пример взят с офф. сайта:
var webPage = require('webpage'); var page = webPage.create(); page.open('http://m.bing.com', function(status) < var title = page.evaluate(function() < return document.title; >); console.log(title); phantom.exit(); >);
Ну тут же все тоже самое загружаете инструмент разработчика , в любом браузере . В хроме и ему подобных (опера , яндекс , рамблер итд) он встроеный в мозиле firebug смотрите что грузится у вас после загрузки страницы , берете этот url подставляете свои параметры и тем же file_get_contents качаете контент
Ну оно и понятно , вы смотрели каким методом выполнен ajax запрос ? если POST то file_get_contents не отработает и тут только CURL. мало информации даете .
Открываете консоль и поочередно отправляете запросы на GET и POST тот что даст результат и является искомым протоколом $.post(«тут ваш url») или $.get(«тут ваш url»)
Похоже я просто передаю неправильный урл. Можно ли через интсрументы разработчика понять куда передаются параметры от angular.js?
я же написал Вам выше , берете урл по которому уходит запрос и проверяете его . angular.js тут не причем , ничего хитрого он де делает . дайте адрес от куда вы хотите спарсить .
Попробуйте подключиться через curl к нужной странице, должно сработать, например:
$curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_FAILONERROR, 1); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); curl_setopt($curl, CURLOPT_POST, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($curl) curl_close($curl);
Такой код напрямую нельзя получать и открывать у себя в браузере. Ты создаёшь клиента-робота и подход тут другой. Берешь $data и с помощью SimpleHTML DOM дальше пилишь. Все это возможно. А если откроешь $data у себя в браузере то это уже кроссдоменный запрос, который может криво работать. Приходилось парсить сайт, где ajax подгружалось абсолютно всё. Прошло всё успешно.
После загрузки страницы и отработки скриптов можно посмотреть результат со всеми изменениями.
С помощью библиотеки CURL это возможно. Недавно сайт парсил где все на ajax и с библиотекой jQuery. Так если парсишь с помощью curl и потом выводим в браузер, то будет все криво, потому-что клиент в данный момент CURL(сервер), а не Вы. Кроссдоменный запрос не прокатит поэтому нужно взять к примеру библиотеку Simple HTMLDOM
$curl = curl_init(); curl_setopt($curl, CURLOPT_FAILONERROR, 1); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // allow redirects curl_setopt($curl, CURLOPT_TIMEOUT, 10); // times out after 4s curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // return into a variable curl_setopt($curl, CURLOPT_URL, "https://ya.ru/"); curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 GTB6"); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($curl);
Выводить $data не нужно. Всё, ваш клиент (сервер) получил страницу. Теперь скачиваем http://simplehtmldom.sourceforge.net/ И есть инструкция например здесь http://zubuntu.ru/php-simple-html-dom-parser/ То есть нам нужно продолжить так:
$html=str_get_html($data); $result=$html->find(div.spisok span); //получаем массив
По такому принципу ищем данные, перебираем их. Важно точно определить «координаты» данных.