Baidu.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Jaeger <JaegerCode@gmail.com>
  5. * Date: 2017/10/1
  6. * Baidu searcher
  7. */
  8. namespace QL\Ext;
  9. use QL\Contracts\PluginContract;
  10. use QL\QueryList;
  11. class Baidu implements PluginContract
  12. {
  13. private $is_pc = true;
  14. protected $ql;
  15. protected $keyword;
  16. protected $pageNumber = 10;
  17. protected $httpOpt = [
  18. 'PC'=>[ 'headers' => [
  19. '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',
  20. 'Accept-Encoding' => 'gzip, deflate, br',
  21. ]],
  22. 'M'=>[ 'headers' => [
  23. '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',
  24. 'Accept-Encoding' => 'gzip, deflate, br',
  25. ]],
  26. ];
  27. const API = [
  28. 'PC' => 'https://www.baidu.com/s',
  29. 'M' => 'https://m.baidu.com/s',
  30. ];
  31. const RULES = [
  32. 'PC' => [
  33. 'title' => ['h3', 'text'],
  34. 'link' => ['h3>a', 'href']
  35. ],
  36. 'M' => [
  37. 'title' => ['h3', 'text'],
  38. 'tpl' => ['', 'tpl'],
  39. 'link' => ['', 'data-log']
  40. ],
  41. ];
  42. const RANGE = [
  43. 'PC' => '.result',
  44. 'M' => '.result'
  45. ];
  46. /**
  47. * @var string
  48. */
  49. private $api;
  50. public function __construct(QueryList $ql, $pageNumber, $api)
  51. {
  52. $this->ql = $ql->rules(self::RULES[$api])->range(self::RANGE[$api]);
  53. $this->pageNumber = $pageNumber;
  54. $this->api = self::API[$api];
  55. $this->is_pc = $api == "PC";
  56. $this->httpOpt=$this->httpOpt[$api];
  57. }
  58. public static function install(QueryList $queryList, ...$opt)
  59. {
  60. $name = $opt[0] ?? 'baidu';
  61. $api = $opt[1] ?? 'PC';
  62. $queryList->bind($name, function ($pageNumber = 10) use ($api) {
  63. return new Baidu($this, $pageNumber, $api);
  64. });
  65. }
  66. public function setHttpOpt(array $httpOpt = [])
  67. {
  68. $this->httpOpt = $httpOpt;
  69. return $this;
  70. }
  71. public function search($keyword)
  72. {
  73. $this->keyword = $keyword;
  74. return $this;
  75. }
  76. public function page($page = 1, $realURL = false)
  77. {
  78. return $this->query($page)->query()->getData(function ($item) use ($realURL) {
  79. if (!$this->is_pc) {
  80. if ($item['tpl']!='www_normal'){
  81. return null;
  82. }
  83. $origin=json_decode($item['link'], true);
  84. unset($item['tpl']);
  85. $item['link'] = $origin['mu'];
  86. } else {
  87. $realURL && $item['link'] = $this->getRealURL($item['link']);
  88. }
  89. return $item;
  90. });
  91. }
  92. public function getCount()
  93. {
  94. if (!$this->is_pc) {
  95. return 1000;
  96. }
  97. $count = 0;
  98. $text = $this->query(1)->find('.nums')->text();
  99. if (preg_match('/[\d,]+/', $text, $arr)) {
  100. $count = str_replace(',', '', $arr[0]);
  101. }
  102. return (int)$count;
  103. }
  104. public function getCountPage()
  105. {
  106. $count = $this->getCount();
  107. $countPage = $this->ceil($count / $this->pageNumber);
  108. return $countPage;
  109. }
  110. protected function query($page = 1)
  111. {
  112. if ($this->is_pc) {
  113. $this->ql->get($this->api, [
  114. 'wd' => $this->keyword,
  115. 'rn' => $this->pageNumber,
  116. 'pn' => $this->pageNumber * ($page - 1)
  117. ], $this->httpOpt);
  118. } else {
  119. $this->ql->get($this->api, [
  120. 'word' => $this->keyword,
  121. 'usm' => $this->pageNumber,
  122. 'pn' => $this->pageNumber * ($page - 1)
  123. ], $this->httpOpt);
  124. }
  125. return $this->ql;
  126. }
  127. /**
  128. * 得到百度跳转的真正地址
  129. * @param $url
  130. * @return mixed
  131. */
  132. protected function getRealURL($url)
  133. {
  134. if (empty($url)) return $url;
  135. $header = get_headers($url, 1);
  136. if (strpos($header[0], '301') || strpos($header[0], '302')) {
  137. if (is_array($header['Location'])) {
  138. //return $header['Location'][count($header['Location'])-1];
  139. return $header['Location'][0];
  140. } else {
  141. return $header['Location'];
  142. }
  143. } else {
  144. return $url;
  145. }
  146. }
  147. }