Hyperf抓取网易云音乐评论
<?php namespace App\Service\Song; use Hyperf\DbConnection\Db; use \Hyperf\Utils\WaitGroup; class SongService { //获取评论的请求地址 private $musicPostUrl = 'https://music.163.com/weapi/v1/resource/comments/R_SO_4_'; /** * todo 【注意】:$musicPage * $musicLimit > 1000的话,接口会请求不了数据,具体原因不详 */ //获取评论分页的页数(目前好像最多请求50页数,超过会请求错误) private $musicPage = 50; //获取评论分页的条数 private $musicLimit = 20; /** * 获取评论 * @param $data */ public function getComment($data = []) { //歌曲名称、歌曲ID $default = [ 'text' => '带我去找夜生活', 'songId' => '1410647903' ]; $data = (!empty($data) ? $data : $default); // 设置请求头 $headers = array( 'Accept:*/*', 'Accept-Language:zh-CN,zh;q=0.9', 'Connection:keep-alive', 'Content-Type:application/x-www-form-urlencoded', 'Host:music.163.com', 'Origin:https://music.163.com', // 模拟浏览器设置 User-Agent ,否则取到的数据不完整 'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' ); // 拼接歌曲的url $url = $this->musicPostUrl . $data['songId'] . '?csrf_token='; // 拼接加密 params 用到的第一个参数 $songName = $data['text']; //利用协程去实现 $wg = new WaitGroup(); $wg->add($this->musicPage); //100并发 for ($j = 0; $j < $this->musicPage; $j++) { $limit = $this->musicLimit; $offset = $j * $limit; $first_param = '{"rid":"R_SO_4_' . $data['songId'] . '","offset":' . $offset . ',"total":"true","limit":' . $limit . ',"csrf_token":""}'; // 记录评论 try { co(function () use ($wg, $j, $first_param, $url, $headers, $songName) { $params = array('params' => $this->aesGetParams($first_param), 'encSecKey' => $this->getEncSecKey()); $htmlInfo = $this->httpPost($url, $headers, http_build_query($params)); $insertData = $this->saveComment(json_decode($htmlInfo, true), $songName); //var_dump($insertData); var_dump("当前循环第:{$j} 次"); //此处为数据库入库: if ($insertData) { Db::table('song')->insert($insertData); } $wg->done(); }); } catch (\Exception $exception) { var_dump($exception->getMessage()); } // 没有设置代理IP,间隔2秒执行(不然网易云爬取不了) ,如需要代理(自行百度代理IP),下面sleep可以不用写 sleep(2); } $wg->wait(); } /** * 加密获取params * @param $param // 待加密的明文信息数据 * @param string $method // 加密算法 * @param string $key // key * @param string $options // options 是以下标记的按位或: OPENSSL_RAW_DATA 、 OPENSSL_ZERO_PADDING * @param string $iv // 非 NULL 的初始化向量 * @return string * * $key 在加密 params 中第一次用的是固定的第四个参数 0CoJUm6Qyw8W8jud,在第二次加密中用的是 js 中随机生成的16位字符串 */ private function aesGetParams($param, $method = 'AES-128-CBC', $key = 'JK1M5sQAEcAZ46af', $options = '0', $iv = '0102030405060708') { $firstEncrypt = openssl_encrypt($param, $method, '0CoJUm6Qyw8W8jud', $options, $iv); $secondEncrypt = openssl_encrypt($firstEncrypt, $method, $key, $options, $iv); return $secondEncrypt; } /** * encSecKey 在 js 中有 res 方法加密。 * 其中三个参数分别为上面随机生成的16为字符串,第二个参数 $second_param,第三个参数 $third_param 都是固定写死的,这边使用抄下来的一个固定 encSecKey * @return bool */ private function getEncSecKey() { $getEncSecKey = '2a98b8ea60e8e0dd0369632b14574cf8d4b7a606349669b2609509978e1b5f96ed8fbe53a90c0bb74497cd2eb965508bff5bfa065394a52ea362539444f18f423f46aded5ed9a1788d110875fb976386aa4f5d784321433549434bccea5f08d1888995bdd2eb015b2236f5af15099e3afbb05aa817c92bfe3214671e818ea16b'; return $getEncSecKey; } /** * curl 发送 post 请求 * @param $url * @param $header * @param $data * @return mixed */ public function httpPost($url, $header, $data) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, 0); // 0不带头文件,1带头文件(返回值中带有头文件) curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 curl_setopt($ch, CURLOPT_AUTOREFERER, 1); // 自动设置Referer curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); //设置等待时间 curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数 $content = curl_exec($ch); curl_close($ch); return $content; } /** * 获取评论内容 * @param $songName * @param $data */ public function saveComment($data, $songName) { if (!($data['comments'] ?? [])) { return false; } foreach ($data['comments'] as $v) { $insertData[] = [ 'user_id' => $v['user']['userId'] ?? 0, 'song_name' => $songName ?? '未知歌曲', 'avatar_url' => $v['user']['avatarUrl'] ?? '', 'parent_comment_id' => $v['parentCommentId'] ?? 0, 'comment_id' => $v['commentId'] ?? 0, 'nickname' => $v['user']['nickname'] ?? '', 'content' => $v['content'] ?? '', 'like_count' => $v['likedCount'] ?? 0, 'ip' => $v['ipLocation']['location'] ?? '未知', 'create_time' => date("Y-m-d H:i:s", $v['time'] / 1000), ]; } return $insertData; } } 本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu
我看刑 :+1:
加密算法和key哪来的