Baidu.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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;
  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. 'link' => ['', 'data-log']
  39. ],
  40. ];
  41. const RANGE = [
  42. 'PC' => '.result',
  43. 'M' => '.result'
  44. ];
  45. /**
  46. * @var string
  47. */
  48. private $api;
  49. public function __construct(QueryList $ql, $pageNumber, $api)
  50. {
  51. $this->ql = $ql->rules(self::RULES[$api])->range(self::RANGE[$api]);
  52. $this->pageNumber = $pageNumber;
  53. $this->api = self::API[$api];
  54. $this->is_pc = $api == "PC";
  55. $this->httpOpt=$this->httpOpt[$api];
  56. }
  57. public static function install(QueryList $queryList, ...$opt)
  58. {
  59. $name = $opt[0] ?? 'baidu';
  60. $api = $opt[1] ?? 'PC';
  61. $queryList->bind($name, function ($pageNumber = 10) use ($api) {
  62. return new Baidu($this, $pageNumber, $api);
  63. });
  64. }
  65. public function setHttpOpt(array $httpOpt = [])
  66. {
  67. $this->httpOpt = $httpOpt;
  68. return $this;
  69. }
  70. public function search($keyword)
  71. {
  72. $this->keyword = $keyword;
  73. return $this;
  74. }
  75. public function page($page = 1, $realURL = false)
  76. {
  77. return $this->query($page)->query()->getData(function ($item) use ($realURL) {
  78. if (!$this->is_pc) {
  79. $item['link'] = json_decode($item['link'], true)['mu'];
  80. } else {
  81. $realURL && $item['link'] = $this->getRealURL($item['link']);
  82. }
  83. return $item;
  84. });
  85. }
  86. public function getCount()
  87. {
  88. if (!$this->is_pc) {
  89. return 1000;
  90. }
  91. $count = 0;
  92. $text = $this->query(1)->find('.nums')->text();
  93. if (preg_match('/[\d,]+/', $text, $arr)) {
  94. $count = str_replace(',', '', $arr[0]);
  95. }
  96. return (int)$count;
  97. }
  98. public function getCountPage()
  99. {
  100. $count = $this->getCount();
  101. $countPage = $this->ceil($count / $this->pageNumber);
  102. return $countPage;
  103. }
  104. protected function query($page = 1)
  105. {
  106. if ($this->is_pc) {
  107. $this->ql->get($this->api, [
  108. 'wd' => $this->keyword,
  109. 'rn' => $this->pageNumber,
  110. 'pn' => $this->pageNumber * ($page - 1)
  111. ], $this->httpOpt);
  112. } else {
  113. $this->ql->get($this->api, [
  114. 'word' => $this->keyword,
  115. 'usm' => $this->pageNumber,
  116. 'pn' => $this->pageNumber * ($page - 1)
  117. ], $this->httpOpt);
  118. }
  119. return $this->ql;
  120. }
  121. /**
  122. * 得到百度跳转的真正地址
  123. * @param $url
  124. * @return mixed
  125. */
  126. protected function getRealURL($url)
  127. {
  128. if (empty($url)) return $url;
  129. $header = get_headers($url, 1);
  130. if (strpos($header[0], '301') || strpos($header[0], '302')) {
  131. if (is_array($header['Location'])) {
  132. //return $header['Location'][count($header['Location'])-1];
  133. return $header['Location'][0];
  134. } else {
  135. return $header['Location'];
  136. }
  137. } else {
  138. return $url;
  139. }
  140. }
  141. }