Як спарсити погоду з sinoptik та відправити через бота телеграм
Блог Фрилансера
15 бер. 2018
І так будемо використовувати DomCrawler та Curl для парсера з siniptik.ua.
Готовий клас для роботи
<?php
namespace \sinoptik;
use Symfony\Component\DomCrawler\Crawler;
class Sinoptik{
public $city;
public $tenDays = false;
const BaseURL = 'https://ua.sinoptik.ua';
public function __construct($city)
{
$this->city = $city;
}
public function getData(){
$page = new Crawler($this->getPageCity());
return $page->filter('#blockDays .main')->each(function (Crawler $node, $i) use ($page){
$id = $node->attr('id');
$day = $node->filter('.day-link')->text();
$date = $node->filter('.date')->text();
$weatherIco = $node->filter('.weatherIco')->attr('title');
$weatherIcoImg = $node->filter('.weatherIco .weatherImg')->attr('src');
$temp_min = $node->filter('.temperature .min span')->text();
$temp_max = $node->filter('.temperature .max span')->text();
$weatherDetails = false;
$idTab = sprintf('#%sc',$id);
if ($i == 0):
$tabNode = $page->filter($idTab);
if ($tabNode){
$weatherDetails = $this->weatherDetails($tabNode);
}
endif;
return [
'id' => $id,
'day'=> $day,
'date'=> $date,
'weatherIco'=> $weatherIco,
'weatherIcoImg'=> $weatherIcoImg,
'tMin'=>$temp_min,
'tMax'=>$temp_max,
'details' => $weatherDetails
];
});
}
/**
* @param Crawler $node
* @return void
*/
private function weatherDetails(Crawler $node){
$weatherDetails = $node->filter('.weatherDetails');
$Th = $node->filter('thead td')->each(function (Crawler $node, $i) {
return $node->text();
});
$Titles = $node->filter('.titles p')->each(function (Crawler $node, $i) {
return $node->text();
});
$Body = $node->filter('tbody tr')->each(function (Crawler $tr, $i) {
return $tr->filter('td')->each(function (Crawler $td, $i) use ($tr){
if ($tr->matches('.weatherIcoS')){
return $td->filter('div')->attr('title');
}
return $td->text();
});
});
array_unshift($Titles,'Години','Погода');
$Body = array_map(function ($s){
return array_chunk($s,2);
},$Body);
$modifiArray = [];
foreach ( $Body as $key=>$items){
foreach ($items as $itemKey=>$item){
$modifiArray[$Titles[$key]][$Th[$itemKey]] = $item;
}
}
return [
'details' => $modifiArray
];
}
/**
* @param bool $TenDays
* @return bool|string
*/
public function getPageCity(){
$url = sprintf('%s/погода-%s',self::BaseURL,$this->city);
if ($this->tenDays){
$url = sprintf('%s/погода-%s/10-днів',self::BaseURL,$this->city);
}
return $this->getPage($url);
}
/**
*
*/
private function getPage($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_COOKIEFILE, __DIR__ . '/cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, __DIR__ . '/cookie.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch);
return $html;
}
}
Приклад використавння.
$sinoptik = new Sinoptik('умань');
//$sinoptik->tenDays = true; // Якщо хочемо прогноз на 10 днів
$data = $sinoptik->getData() //- поверне дані
Приклад для генерації тексту в телеграм
$sinoptik = new Sinoptik('київ');
//$sinoptik->tenDays = true;
$text = '';
$i = 0;
foreach ($sinoptik->getData() as $day) {
$text .= sprintf('🗓 %s <i>%s</i>',$day['day'],$day['date']).PHP_EOL;
$text .= sprintf('%s</i>',$day['weatherIco']).PHP_EOL;
$text .= sprintf('🌡 Від <i>%s</i> до <i>%s</i>',$day['tMin'],$day['tMax']).PHP_EOL;
$text .= '________________'.PHP_EOL.PHP_EOL;
if ($i == 2) break;
$i++;
}
// $text - містить текст повідомлення