Так как Instagram и Facebook ограничили доступ к API, а фото с своего аккаунта всё же нужно периодически получать и выводить на сайте, остается вариант их спарсить.
Сразу нужно сказать что метод не стабильный и требует постоянного контроля и доработки.
Если открыть исходный код страницы любого профиля, то видно что весь контент хранится в JS-объекте window._sharedData
, в котором можно найти 12 последних фото, описания к ним и другую информацию.
У инстаграма есть огромный черный список IP-адресов, скорее всего адрес вашего хостинга заблокирован, и обычным Curl-запросом будет возвращаться 302-й редирект на страницу авторизации:
HTTP/1.1 302 Found
Content-Type: text/html; charset=utf-8
Location: https://www.instagram.com/accounts/login/
...
Решение: использовать прокси, но они тоже со временем блокируются, поэтому проблематично найти рабочий сервер.
$ch = curl_init('https://www.instagram.com/аккаунт/');
curl_setopt($ch, CURLOPT_PROXY, 'xxx.xxx.xxx.xxx:8080');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false); // true - чтобы вывести заголовки
$html = curl_exec($ch);
curl_close($ch);
echo $html;
Страницу получили, теперь нужно удалить из полученного кода все управляющие символы, они будут мешать в следующем этапе.
// Удаление управляющих символов
for ($i = 0; $i <= 31; ++$i) {
$html = str_replace(chr($i), '', $html);
}
// Удаление символа Delete
$html = str_replace(chr(127), '', $html);
Регулярным выражением получаем объект window._sharedData
и преобразуем его в массив с помощью функции json_decode(). Далее собираем массив с данными.
$data = array();
preg_match_all('/<script type="text\/javascript">window\._sharedData = \{(.*)\};<\/script>/ism', $html, $matches);
if (!empty($matches[1][0])) {
$res = json_decode('{' . $matches[1][0] . '}', true);
$media = $res['entry_data']['ProfilePage'][0]['graphql']['user']['edge_owner_to_timeline_media']['edges'];
if (!empty($media)) {
foreach ($media as $row) {
//print_r($row['node']);
$data[] = array(
'id' => $row['node']['id'],
'text' => $row['node']['edge_media_to_caption']['edges'][0]['node']['text'],
'image' => $row['node']['thumbnail_src'],
);
}
}
}
print_r($data);
Результат:
Array(
[0] => Array(
[id] => xxxxxxxxxxxxxxxxx
[text] => Высокая кухня и красивые друзья❤️❤️
[image] => https://...
)
[1] => Array(
[id] => xxxxxxxxxxxxxxxxx
[text] => Спасибо за вчерашний вечер❤️❤️ Настоящее предновогоднее настроение?
[image] => https://...
)
...
)
Полученный массив можно добавить в БД и сохранить изображения, обрабатывая только новые записи. Структура MySQL таблицы:
CREATE TABLE IF NOT EXISTS `instagram` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`insta_id` int(11) UNSIGNED DEFAULT '0',
`text` text NOT NULL,
`file` varchar(255) NOT NULL DEFAULT '',
`date` int(11) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Циклом проходим по массиву и проверяем наличие фото в базе, если нет – добавляем.
// Подключение к БД
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль');
if (!empty($data)) {
foreach ($data as $row) {
// Проверяем есть ли такой ID в БД
$sth = $dbh->prepare("SELECT * FROM `instagram` WHERE `insta_id` = ?");
$sth->execute(array($row['id']));
$is_db = $sth->fetch(PDO::FETCH_ASSOC);
if (empty($is_db)) {
// Получаем url файла без GET-параметров и его расширение
$url = $row['image'];
$url = explode('?', $url);
$ext = mb_strtolower(mb_substr(mb_strrchr($url[0], '.'), 1));
$file = $row['id'] . '.' . $ext;
// Сохранение файла на сервере и добавление в БД
if (copy($row['image'], __DIR__ . '/instagram/' . $file)) {
$sth = $dbh->prepare("
INSERT INTO
`instagram`
SET
`insta_id` = :insta_id,
`text` = :text,
`file` = :file,
`date` = :date
");
$sth->execute(array(
'insta_id' => $row['id'],
'text' => $row['text'],
'file' => $file,
'date' => time(),
));
}
}
}
}
<?php
// Подключение к БД
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль');
$sth = $dbh->prepare("SELECT * FROM `instagram` ORDER BY `date` DESC LIMIT 20");
$sth->execute();
$list = $sth->fetchAll(PDO::FETCH_ASSOC);
?>
<ul>
<?php foreach ($list as $row): ?>
<li>
<a href="/instagram/<?php echo $row['file']; ?>">
<img src="/instagram/<?php echo $row['file']; ?>" alt="">
</a>
</li>
<?php endforeach; ?>
</ul>
Можно ли рассчитывать на автоматизацию доступа к изображениям и отсутствии пролем в течении месяцев?
Можно писать в личку.
Заметил особенность - на некоторых хостах при загрузке страницы курлом сохраняет страницу с логином, значит с этого IP было много запросов и инстаграм их добавил в бан, а с некоторых сохраняет реальную страницу с данными. Потому не обязательно использовать прокси.
А больше чем 12 фото курл может увидеть. пролистать вниз?
anufrieff-a "собака" mail.ru
Заранее, благодарен!