Як спарсити погоду з sinoptik та відправити через бота телеграм

Блог Фрилансера 5 хвилин 6 секунд 15 бер. 2018
 Як спарсити погоду з sinoptik та відправити через бота телеграм

 


І так будемо використовувати 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 - містить текст повідомлення