Scraper danych z empika

Nie tak dawno temu dostałem zlecenie napisania skryptu pobierającego dane, dla księgarni internetowej opartej o PrestaShop. Klient chciał rozszerzyć swój asortyment, natomiast nie miał ochoty wydawać pieniążków na copywriterów.

Za pomocą PHP pobraliśmy listę synonimów oraz dane dotyczące konkretnych produktów. Postanowiłem, że opublikuje część kodu odpowiedzialną za scraping danych ze strony empiku.

Całość do poprawnego działania wymaga pobrania klasy simple_html_dom.

<?php
namespace pl.kmagdziarz;

require_once 'simple_html_dom.php';

@define("ROOT_WWW", "http://www.empik.com");
@define("PRODUCT_PER_PAGE", "?resultsPP=60");
@define("SEPARATOR","/");


class OneProduct
{
    private $htmlsource;
    private $photo;
    private $link;

    // Element
    private $wydawnictwo;
    private $jezyk_wydania;
    private $jezyk_oryginalu;
    private $autor;
    private $tytul;
    private $tytul_oryginalny;
    private $dlugi_opis;
    private $ilosc_stron;
    private $data_premiery;
    private $rok_wydania;
    private $rozmiar;

    /**
     * OneProduct constructor.
     * @param $product_adress
     */
    public function __construct($product_adress)
    {
        $this->link = $product_adress;

        $this->htmlsource = $this->getContentWWW(ROOT_WWW.$product_adress);
        $this->getDetails();
    }

    /**
     * @param $adres
     * @return bool|\simple_html_dom
     */
    private function getContentWWW($adres)
    {
        $chf = curl_init();
        curl_setopt($chf, CURLOPT_URL, $adres);
        curl_setopt($chf, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($chf, CURLOPT_RETURNTRANSFER, 1);
        $danef = curl_exec($chf);
        if(curl_errno($chf)){
            echo 'Curl error: ' . curl_error($chf);
        }
        curl_close($chf);
        return str_get_html($danef);
    }

    /**
     * @return string
     */
    private function getLongDescryption()
    {
        return trim($this->htmlsource->find('div[class=contentPacketText longDescription]',0)->plaintext);
    }

    /**
     * @return array
     */
    private function getImage()
    {
        $arr = array($this->htmlsource->find('a[rel=lightbox]',0)->href);

        $el = $this->htmlsource->find('div[class=contentPacket layerGalleryContainer]',0);
        if($el)
            foreach(str_get_html($el)->find('a') as $element)
                array_push($arr,$element->href);

        return array_unique($arr);
    }

    /**
     * @return bool
     */
    private function getDetails()
    {
        $arr = $this->htmlsource->find('tr[class=productDetailsSet row--text]');

        if(count($arr) == 0)
            return false;

        foreach ($arr as $param)
        {
            $title_box = str_get_html($param)->find('td[class=productDetailsLabel]');
            $content_box = str_get_html($param)->find('td[class=productDetailsValue]');

            if(isset($title_box[0],$content_box[0]))
            {
                switch (true)
                {
                    case strpos(strtolower($title_box[0]),"wydawnictwo"):
                        $this->wydawnictwo = trim($content_box[0]->plaintext);
                        break;
                    case strpos(strtolower($title_box[0]),"język wydania"):
                        $this->jezyk_wydania = trim($content_box[0]->plaintext);
                        break;
                    case strpos(strtolower($title_box[0]),"język oryginału"):
                        $this->jezyk_oryginalu = trim($content_box[0]->plaintext);
                        break;
                    case strpos(strtolower($title_box[0]),"ilość stron"):
                        $this->ilosc_stron = trim($content_box[0]->plaintext);
                        break;
                    case strpos(strtolower($title_box[0]),"data premiery"):
                        $this->data_premiery = trim($content_box[0]->plaintext);
                        break;
                    case strpos(strtolower($title_box[0]),"rok wydania"):
                        $this->rok_wydania = trim($content_box[0]->plaintext);
                        break;
                    case strpos(strtolower($title_box[0]),"tytuł oryginalny"):
                        $this->tytul_oryginalny = trim($content_box[0]->plaintext);
                        break;
                    case strpos(strtolower($title_box[0]),"tytuł"):
                        $this->tytul = trim($content_box[0]->plaintext);
                        break;
                    case strpos(strtolower($title_box[0]),"autor"):
                        $this->autor = trim($content_box[0]->plaintext);
                        break;
                    case strpos(strtolower($title_box[0]),"rozmiar"):
                        $this->rozmiar = trim($content_box[0]->plaintext);
                        break;
                }
            }
            else
                continue;
        }

        $this->photo = $this->getImage();
        $this->dlugi_opis = $this->getLongDescryption();

        return true;
    }

    /**
     * @return string
     */
    public function showAll()
    {
        return
            "<br />Tytuł: ".$this->tytul
            ."<br />Autor: ".$this->autor
            ."<br />Tytuł oryginalny: ".$this->tytul_oryginalny
            ."<br />Wydawnictwo: ".$this->wydawnictwo
            ."<br />Język wydania: ".$this->jezyk_wydania
            ."<br />Język oryginału: ".$this->jezyk_oryginalu
            ."<br />Ilość stron: ".$this->ilosc_stron
            ."<br />Data premiery: ".$this->data_premiery
            ."<br />Rok wydania: ".$this->rok_wydania
            ."<br />Rozmiar: ".$this->rozmiar
            ."<br />Opis: ".$this->dlugi_opis;
    }

    /**
     * @return array
     */
    public function getAll()
    {
        return array(
            'tytul' => $this->tytul,
            'autor' => $this->autor,
            'tytul_oryginalny' => $this->tytul_oryginalny,
            'wydawnictwo' => $this->wydawnictwo,
            'jezyk_wydania' => $this->jezyk_wydania,
            'jezyk_oryginalu' => $this->jezyk_oryginalu,
            'ilosc_stron' => $this->ilosc_stron,
            'data_premiery' => $this->data_premiery,
            'rok_wydania' => $this->rok_wydania,
            'rozmiar' => $this->rozmiar,
            'opis' => $this->dlugi_opis,
            'photo' => $this->photo,
            'link' => $this->link
        );
    }
}

Myślę, że resztę kodu można dopisać sobie analogicznie 🙂

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *