* Date: 2017/10/1 * Baidu searcher */ namespace QL\Ext; use QL\Contracts\PluginContract; use QL\QueryList; class Baidu implements PluginContract { private $is_pc = true; protected $ql; protected $keyword; protected $pageNumber = 10; protected $httpOpt = [ 'PC'=>[ 'headers' => [ 'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36', 'Accept-Encoding' => 'gzip, deflate, br', ]], 'M'=>[ 'headers' => [ 'User-Agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1', 'Accept-Encoding' => 'gzip, deflate, br', ]], ]; const API = [ 'PC' => 'https://www.baidu.com/s', 'M' => 'https://m.baidu.com/s', ]; const RULES = [ 'PC' => [ 'title' => ['h3', 'text'], 'link' => ['h3>a', 'href'] ], 'M' => [ 'title' => ['h3', 'text'], 'tpl' => ['', 'tpl'], 'link' => ['', 'data-log'] ], ]; const RANGE = [ 'PC' => '.result', 'M' => '.result' ]; /** * @var string */ private $api; public function __construct(QueryList $ql, $pageNumber, $api) { $this->ql = $ql->rules(self::RULES[$api])->range(self::RANGE[$api]); $this->pageNumber = $pageNumber; $this->api = self::API[$api]; $this->is_pc = $api == "PC"; $this->httpOpt=$this->httpOpt[$api]; } public static function install(QueryList $queryList, ...$opt) { $name = $opt[0] ?? 'baidu'; $api = $opt[1] ?? 'PC'; $queryList->bind($name, function ($pageNumber = 10) use ($api) { return new Baidu($this, $pageNumber, $api); }); } public function setHttpOpt(array $httpOpt = []) { $this->httpOpt = $httpOpt; return $this; } public function search($keyword) { $this->keyword = $keyword; return $this; } public function page($page = 1, $realURL = false) { return $this->query($page)->query()->getData(function ($item) use ($realURL) { if (!$this->is_pc) { if ($item['tpl']!='www_normal'){ return null; } $origin=json_decode($item['link'], true); unset($item['tpl']); $item['link'] = $origin['mu']; } else { $realURL && $item['link'] = $this->getRealURL($item['link']); } return $item; }); } public function getCount() { if (!$this->is_pc) { return 1000; } $count = 0; $text = $this->query(1)->find('.nums')->text(); if (preg_match('/[\d,]+/', $text, $arr)) { $count = str_replace(',', '', $arr[0]); } return (int)$count; } public function getCountPage() { $count = $this->getCount(); $countPage = $this->ceil($count / $this->pageNumber); return $countPage; } protected function query($page = 1) { if ($this->is_pc) { $this->ql->get($this->api, [ 'wd' => $this->keyword, 'rn' => $this->pageNumber, 'pn' => $this->pageNumber * ($page - 1) ], $this->httpOpt); } else { $this->ql->get($this->api, [ 'word' => $this->keyword, 'usm' => $this->pageNumber, 'pn' => $this->pageNumber * ($page - 1) ], $this->httpOpt); } return $this->ql; } /** * 得到百度跳转的真正地址 * @param $url * @return mixed */ protected function getRealURL($url) { if (empty($url)) return $url; $header = get_headers($url, 1); if (strpos($header[0], '301') || strpos($header[0], '302')) { if (is_array($header['Location'])) { //return $header['Location'][count($header['Location'])-1]; return $header['Location'][0]; } else { return $header['Location']; } } else { return $url; } } }