Advertisement
Artur_Hopf

Untitled

Oct 23rd, 2019
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 14.02 KB | None | 0 0
  1. <?php
  2.  
  3. namespace common\models;
  4.  
  5. use Yii;
  6. use yii\base\Model;
  7. use keltstr\simplehtmldom\SimpleHTMLDom;
  8. use yii\helpers\Json;
  9.  
  10. class Parser extends Model
  11. {
  12.     public $url;
  13.     public $html;
  14.     public $old_watermark;
  15.  
  16.     const MAX_TRIES = 4;
  17.     const MAX_IMAGES = 7;
  18.     const PROXY_USER = "proxyuser:qwer4123";
  19.     const PROXY_FILE = "/home/pdftour/public_html/proxy.txt";
  20.  
  21.     public static function getProxy($all = false)
  22.     {
  23.         if ($file = file_get_contents(static::PROXY_FILE)) {
  24.             $proxies = explode("\n", $file);
  25.  
  26.             if ($all) {
  27.                 return $proxies;
  28.             }
  29.  
  30.             return trim($proxies[rand(0, count($proxies) - 1)]);
  31.         }
  32.  
  33.         return false;
  34.     }
  35.  
  36.     public static function testProxy($proxies, $url = "https://www.cian.ru/")
  37.     {
  38.         set_time_limit(0);
  39.  
  40.         $goodProxies = [];
  41.  
  42.         for ($i = 0; $i < count($proxies); $i++) {
  43.             $ch = curl_init($url);
  44.             curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  45.             curl_setopt($ch, CURLOPT_HTTPHEADER, [
  46.                 'Pragma: no-cache',
  47.                 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,uk;q=0.2',
  48.                 'Upgrade-Insecure-Requests: 1',
  49.                 'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
  50.                 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
  51.                 'Cache-Control: no-cache',
  52.                 'Connection: keep-alive',
  53.             ]);
  54.  
  55.             curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  56.             curl_setopt($ch, CURLOPT_TIMEOUT, 10);
  57.             curl_setopt($ch, CURLOPT_PROXY, $proxies[$i]);
  58.  
  59.             curl_setopt($ch, CURLOPT_PROXYUSERPWD, static::PROXY_USER);
  60.  
  61.             $data = curl_exec($ch);
  62.  
  63.             if (strlen($data) > 100000) {
  64.                 $goodProxies[] = $proxies[$i];
  65.             }
  66.         }
  67.         return $goodProxies;
  68.     }
  69.  
  70.  
  71.     public static function request($url)
  72.     {
  73.         $data = "";
  74.         $sleep = 0;
  75.         for ($i = 0; $i < static::MAX_TRIES  * 2; $i++) {
  76.             $ch = curl_init($url);
  77.  
  78.             curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  79.             curl_setopt($ch, CURLOPT_HTTPHEADER, [
  80.                 'Pragma: no-cache',
  81.                 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,uk;q=0.2',
  82.                 'Upgrade-Insecure-Requests: 1',
  83.                 'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
  84.                 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
  85.                 'Cache-Control: no-cache',
  86.                 'Connection: keep-alive',
  87.             ]);
  88.  
  89.             $proxy = static::getProxy();
  90.  
  91.             curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  92.             curl_setopt($ch, CURLOPT_TIMEOUT, 6);
  93.             curl_setopt($ch, CURLOPT_PROXY, $proxy);
  94.             curl_setopt($ch, CURLOPT_PROXYUSERPWD, static::PROXY_USER);
  95.  
  96.             $data = curl_exec($ch);
  97. //            file_put_contents("/tmp/cian" . $proxy, $data);
  98.             if (strlen($data) > 1000) {
  99.                 if($sleep > 1)
  100.                 {
  101.                     return $data;
  102.                 }
  103.                 $sleep++;
  104.             }
  105.         }
  106. //        file_put_contents("/tmp/cian", $data);
  107.         return false;
  108.     }
  109.  
  110.     public static function multiRequest($urls)
  111.     {
  112.         $responses = [];
  113.  
  114.         for ($i = 0; $i < static::MAX_TRIES && !empty($urls); $i++) {
  115.             $multi = curl_multi_init();
  116.             $channels = [];
  117.  
  118.             foreach ($urls as $index => $url) {
  119.                 $ch = curl_init($url);
  120.                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  121.                 curl_setopt($ch, CURLOPT_HTTPHEADER, [
  122.                     'Pragma: no-cache',
  123.                     'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,uk;q=0.2',
  124.                     'Upgrade-Insecure-Requests: 1',
  125.                     'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
  126.                     'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
  127.                     'Cache-Control: no-cache',
  128.                     'Connection: keep-alive',
  129.                 ]);
  130.  
  131.                 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  132.                 curl_setopt($ch, CURLOPT_TIMEOUT, 8);
  133.                 curl_setopt($ch, CURLOPT_PROXY, static::getProxy());
  134.                 curl_setopt($ch, CURLOPT_PROXYUSERPWD, static::PROXY_USER);
  135.                 curl_multi_add_handle($multi, $ch);
  136.                 $channels[$index] = $ch;
  137.             }
  138.  
  139.             $running = NULL;
  140.             do {
  141.                 curl_multi_exec($multi, $running);
  142.             } while ($running > 0);
  143.  
  144.             foreach ($channels as $index => $channel) {
  145.                 $response = curl_multi_getcontent($channel);
  146.                 if (strlen($response) > 1000) {
  147.                     $responses[] = $response;
  148.                     unset($urls[$index]);
  149.                 }
  150.                 curl_multi_remove_handle($multi, $channel);
  151.             }
  152.  
  153.             curl_multi_close($multi);
  154.         }
  155.  
  156.         return $responses;
  157.     }
  158.  
  159.     public function loadHtml()
  160.     {
  161.         if ($response = static::request($this->url)) {
  162.  
  163.             $this->html = SimpleHTMLDom::str_get_html($response);
  164.             return true;
  165.         }
  166.         return false;
  167.     }
  168.  
  169.     public function parseHtml()
  170.     {
  171.  
  172.         $html = $this->html;
  173.  
  174. //        if (Yii::$app->user->id == 5) {
  175. //           echo $html;
  176. //            exit();
  177. //        }
  178.  
  179.  
  180. //        if ($_SERVER['REMOTE_ADDR'] == '176.100.15.166') {
  181. //            echo ($html);
  182. //            exit();
  183. //            return false;
  184. //        }
  185. //
  186.  
  187.  
  188.         if (empty($html)) {
  189.             return false;
  190.         }
  191.  
  192.         $model = new Realty();
  193.  
  194.  
  195.         $price = '';
  196.         if ($htmlBlock = $html->find('[itemprop="price"]', 0)) {
  197.          //   $price = static::whitespace(preg_replace('/[^\d]+/', '', $htmlBlock->plaintext));
  198.             $price = static::whitespace(str_replace('₽', 'руб', $htmlBlock->plaintext));
  199.         }
  200.  
  201.  
  202.         if (strpos($this->url , '/rent/') === false) {
  203.             $title = "Продажа ";
  204.         } else {
  205.             $title = "Аренда ";
  206.         }
  207.  
  208.         $address = '';
  209.         if ($htmlBlock = $html->find("address", 0)) {
  210.             $address = static::whitespace(str_replace('На карте', '', $htmlBlock->plaintext));
  211.         }
  212.  
  213.         if ($htmlBlock = $html->find('[class*="header-information--"] [class*="title--"]', 0)) {
  214.             $title .= static::whitespace($htmlBlock->plaintext) . ', ';
  215.         }
  216.  
  217.         $title .= $address;
  218.         $title = str_replace(" на длительный срок (от года)", "", $title);
  219.  
  220.  
  221.         $images = [];
  222.  
  223.         $imageUrls = [];
  224.  
  225.  
  226.         preg_match_all('/"thumbnailUrl":"([^"]+)"/', $html, $matches);
  227.         if (!empty($matches[1])) {
  228.             foreach ($matches[1] as $url) {
  229.                 $imageUrls[] = str_replace(['\u002F', '1.jpg'], ['/', '2.jpg'], $url);
  230.             }
  231.         }
  232.  
  233. //        foreach ($html->find('img[class^="photo"]') as $image) {
  234. //            $imageUrls[] = str_replace(['\u002F', '1.jpg'], ['/', '2.jpg'], $image->getAttribute("src"));
  235. //        }
  236.  
  237.  
  238.         $imageResponses = static::multiRequest($imageUrls);
  239.  
  240.         foreach ($imageResponses as $response) {
  241.             $filename = Yii::$app->security->generateRandomString() . ".jpg";
  242.             $fullName = Yii::getAlias('@frontend/web/images/tmp/') . $filename;
  243.  
  244.             file_put_contents($fullName, $response);
  245.  
  246.             try {
  247.                 if (exif_imagetype($fullName) == IMAGETYPE_JPEG) {
  248.                     $src = imagecreatefromjpeg($fullName);
  249.                     $imageWidth = imagesx($src);
  250.                     $imageHeight = imagesy($src);
  251.  
  252.                     if ($imageHeight < 100) {
  253.                      //   throw new \Exception("small image");
  254.                     }
  255.                  /*  
  256.                     if (!empty($this->old_watermark)) {
  257.                         $imageHeight = $imageHeight - 81;
  258.                     } else {
  259.                         $imageHeight = $imageHeight - 138;  
  260.                     }                    
  261.  
  262.                     $ratio = 2/3;
  263.  
  264.                     $sourceY = $sourceX = 0;
  265.                     $newImageHeight = $imageHeight;
  266.                     $newImageWidth = $imageWidth;
  267.                     if ($imageHeight / $imageWidth > $ratio) {
  268.                         $newImageHeight = intval($imageWidth * $ratio);
  269.                         $sourceY = intval(($imageHeight - $newImageHeight) / 2);
  270.                     } else {
  271.                         $newImageWidth = intval($newImageHeight / $ratio);
  272.                         $sourceX = intval(($imageWidth - $newImageWidth) / 2);
  273.                     }
  274.  
  275.                    
  276.                     $dest = imagecreatetruecolor($newImageWidth, $newImageHeight);
  277.                     imagecopy($dest, $src, 0, 0, $sourceX, $sourceY, $newImageWidth, $newImageHeight);
  278.                     */
  279.     //                if (empty($this->old_watermark)) {
  280.       //                  $white = imagecolorallocate($dest, 255, 255, 255);
  281.         //                imagefilledrectangle ($dest, $newImageWidth - 340, $newImageHeight - 170, $newImageWidth - 1, $newImageHeight - 1, 0xffffff);
  282.           //          }
  283.                    
  284.                    
  285.                  //   imagejpeg($dest, $fullName);
  286.                     imagejpeg($src, $fullName);
  287.  
  288.                     $images[] = $filename;
  289.                 } else {
  290.                     unlink($fullName);
  291.                 }
  292.             } catch (\Exception $e) {
  293.                 try {
  294.                     unlink($fullName);
  295.                 } catch (\Exception $e) {
  296.  
  297.                 }
  298.             }
  299.         }
  300.  
  301.         $description = '';
  302.         if ($htmlBlock = $html->find('p[class*="description-text--"]', 0)) {
  303.     /*        $description = $htmlBlock->innertext;
  304.             $description = static::whitespace($description);
  305.             $description = preg_replace('/^.+<br\/?>.*<br\/?>/', '', $description);
  306.             $description = preg_replace('/<div.+$/', '', $description);
  307.             $description = preg_replace('/<br \/>.+$/', '', $description);*/
  308.             $description = $htmlBlock->plaintext;
  309.         }
  310.  
  311.  
  312.         $fields = [];
  313.  
  314.         $fields['Адрес'] = $address;
  315.  
  316.  
  317.  
  318.         if ($htmlBlock = $html->find('[class*="underground_link--"]', 0)) {
  319.             $fields['Метро'] = static::whitespace($htmlBlock->plaintext);
  320.         }
  321.  
  322.         if ($htmlBlock = $html->find('[class*="underground_time--"]', 0)) {
  323.             $fields['До метро'] = static::whitespace(str_replace(',', '', $htmlBlock->plaintext));
  324.         }
  325.  
  326. //        foreach ($html->find("table.object_descr_props tr") as $tableRow) {
  327. //            if (($tableTh = $tableRow->find("th", 0)) && ($tableTd = $tableRow->find("td", 0))
  328. //                && !empty($name = static::whitespace($tableTh->plaintext))
  329. //                && !empty($value = static::whitespace($tableTd->plaintext))) {
  330. //                $fields[str_replace(":", "", $name)] = $value;
  331. //            }
  332. //        }
  333. //
  334. //
  335. //        if ($htmlBlock = $html->find(".cf-comm-offer-detail__section", 0)) {
  336. //            $nameRows = $html->find(".cf-comm-offer-detail__prop-name");
  337. //            $valRows = $html->find(".cf-comm-offer-detail__prop-val");
  338. //            if ($nameRows && $valRows) {
  339. //                for ($i = 0; $i < count($nameRows) && $i < count($valRows); $i++) {
  340. //                    if (!empty($name = static::whitespace($nameRows[$i]->plaintext))
  341. //                        && !empty($value = static::whitespace($valRows[$i]->plaintext))
  342. //                    ) {
  343. //                        $fields[str_replace(":", "", $name)] = $value;
  344. //                    }
  345. //                }
  346. //            }
  347. //        }
  348.  
  349.  
  350.  
  351.         foreach ($html->find('[class*="info-block--"] [class*="info--"]') as $infoBlock) {
  352.             if (($nameBlock = $infoBlock->find('[class*="info-title--"]', 0)) && ($valueBlock = $infoBlock->find('[class*="info-text"]', 0))
  353.                 && !empty($name = static::whitespace($nameBlock->plaintext))
  354.                 && !empty($value = static::whitespace($valueBlock->plaintext))) {
  355.                 $fields[str_replace(":", "", $name)] = $value;
  356.             }
  357.         }
  358.  
  359.  
  360.         $coordinates = '';
  361.         try {
  362.             preg_match('/{"lng":(\d+.\d+),"lat":(\d+.\d+)}/', $html->outertext, $matches);
  363.             $coordinates = $matches[1] . "," . $matches[2];
  364.         } catch (\Exception $e) {
  365.             $coordinates = '';
  366.         }
  367.  
  368.  
  369.         $model->attributes = [
  370.             'url' => $this->url,
  371.             'image_urls' => Json::encode($images),
  372.             'title' => $title,
  373.             'coordinates' => $coordinates,
  374.             'price' => $price,
  375.             'user_id' => Yii::$app->user->id,
  376.             'description' => $description,
  377.             'fields' => Json::encode($fields),
  378.         ];
  379.  
  380. //        file_put_contents(__DIR__ .  "/../../frontend/runtime/loglog", print_r($model->attributes, true));
  381.  
  382.         if ($model->save()) {
  383.             $activity = new UserActivity();
  384.             $activity->attributes = [
  385.                 'user_id' => Yii::$app->user->id,
  386.                 'type' => UserActivity::TYPE_PARSING,
  387.                 'url' => $this->url,
  388.             ];
  389.             $activity->save();
  390.             return true;
  391.         }
  392.         file_put_contents(__DIR__ .  "/../../frontend/runtime/loglog", print_r($model->errors, true));
  393.  
  394.         return false;
  395.     }
  396.  
  397.     public static function whitespace($string)
  398.     {
  399.         return html_entity_decode(trim(preg_replace('/\s+/', ' ', str_replace("&nbsp;", " ", $string))));
  400.     }
  401. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement