<?php namespace App\Repositories; use App\Helpers\Constants; use App\Models\CrawlerListen; use App\Models\Track; use Sunra\PhpSimple\HtmlDomParser; use Yangqi\Htmldom\Htmldom; class TrackRepository extends BaseRepository { public function __construct() { } /** * Lấy ds bài hát đã insert * * doanpv - 24/03/2020 * * @param string $pluck_by_field * @param string $type * @param array $select_fields * * @return array */ public function getTrackInserted($pluck_by_field='all', $type='original', array $select_fields) { if (count($select_fields) == 0) $select_fields = ['id', 'title', 'slug']; $query = Track::select($select_fields); if ($pluck_by_field == 'all') { return $query->get()->toArray(); } switch ($type) { case 'upper': return $query->pluck($pluck_by_field)->map(function ($item){ return strtoupper($item); })->all(); break; case 'lower': return $query->pluck($pluck_by_field)->map(function ($item){ return strtolower($item); })->all(); break; default: return $query->pluck($pluck_by_field)->toArray(); } } /** * Lấy ds bài hát chưa có ảnh đại diện (trường art: null) * * doanpv - 24/03/2020 * * @return array */ public function getTrackImageEmpty($limit=200) { $query = Track::select(['id', 'art', 'id_zing', 'id_nct', 'id_keeng', 'src_thumbnail_medium']) ->whereNull('art') ->whereNotNull('src_thumbnail_medium') ->take($limit); return $query->get()->toArray(); } /** * Crawler thông tin bài hát từ url top 100: https://www.nhaccuatui.com/top100/top-100-nhac-tre.m3liaiy6vVsF.html * Nhưng URL này không lấy được link của bài hát và thời lượng * Sử dụng link dạng playlist của top 100 thì lấy được link và thời lượng * URL playlist của top 100: https://www.nhaccuatui.com/playlist/top-100-nhac-tre-hay-nhat-va.m3liaiy6vVsF.html?st=1 * Sử dụng composer package "sunra/php-simple-html-dom-parser" * * @param $url * @return array */ public function processNctGetTrackInfoFromTop100($url) { $tracks = []; $dom = getDom($url); /* Lấy tên bài hát ------------------------------------------------------------------------------------------ */ $element_track_title = 'div.box_info_field h3.h3 a'; foreach ($dom->find($element_track_title) as $data) { $tracks['title'][] = str_replace(['<h2 class="card-header">', '</h2>'], ['', ''], $data->innertext); } /* Lấy đường dẫn ảnh của bài hát ---------------------------------------------------------------------------- */ $element_track_img = 'div.box_info_field a img'; foreach ($dom->find($element_track_img) as $data) { $tracks['img'][] = str_replace(['<h2 class="card-header">', '</h2>'], ['', ''], $data->{"data-src"}); } /* Lấy link bài hát ----------------------------------------------------------------------------------------- */ $element_track_link = 'div.box_info_field h3.h3 a'; foreach ($dom->find($element_track_link) as $data) { $link = str_replace(['<h2 class="card-header">', '</h2>'], ['', ''], $data->href); $tracks['link'][] = $link; } /* Lấy tên ca sĩ hát ---------------------------------------------------------------------------------------- */ $element_track_singer = 'div.box_info_field h4.list_name_singer a'; foreach ($dom->find($element_track_singer) as $data) { $tracks['singer'][] = str_replace(['<h2 class="card-header">', '</h2>'], ['', ''], $data->innertext); } /* Lấy url thông tin cá nhân ca sĩ -------------------------------------------------------------------------- */ $element_singer_profile = 'div.box_info_field h4.list_name_singer a'; foreach ($dom->find($element_singer_profile) as $data) { $tracks['url_profile'][] = str_replace(['<h2 class="card-header">', '</h2>'], ['', ''], $data->href); } /* Lấy ID dạng chuỗi của bài hát ---------------------------------------------------------------------------- */ $element_track_id_str = 'div.box_song_action a.button_add_playlist'; foreach ($dom->find($element_track_id_str) as $data) { $tracks['id_nct_str'][] = str_replace(['btnShowBoxPlaylist_', '</h2>'], ['', ''], $data->id); } /* Lấy ID dạng số của bài hát ------------------------------------------------------------------------------- */ $element_track_id = 'div.box_info_field'; $start = '<span class=\"export_listen\" id="NCTCounter__'; $end = '">0<\/span>'; $rule = "/$start(.*)$end/msU"; foreach ($dom->find($element_track_id) as $data) { $data_crawler = str_replace(['<!--', '-->'], ['', ''], $data); preg_match($rule, $data_crawler, $result); if (is_array($result) && count($result) == 2) { $tracks['id_nct'][] = $result[1]; } } /* Tổng hợp dữ liệu thành mảng ------------------------------------------------------------------------------ */ $result = []; for($i=0; $i < count($tracks['title']); $i++) { $result[$i]['id_nct_str'] = $tracks['id_nct_str'][$i]; $result[$i]['id_nct'] = $tracks['id_nct'][$i]; $result[$i]['title'] = $tracks['title'][$i]; $result[$i]['link'] = $tracks['link'][$i]; $result[$i]['img'] = $tracks['img'][$i]; } return $result; } /** * Lấy link và thời lượng của bài hát từ link playlist của top 100 * URL: https://www.nhaccuatui.com/playlist/top-100-nhac-tre-hay-nhat-va.m3liaiy6vVsF.html?st=1 * Sử dụng composer package "yangqi/htmldom" * * @param $url * @return array */ public function processNctGetTrackInfoFromTop100Playlist($url) { $tracks = []; $dom = new Htmldom($url); /* Lấy ID dạng chuỗi của bài hát ---------------------------------------------------------------------------- */ $element_track_id_str = 'li'; foreach ($dom->find($element_track_id_str) as $data) { if (isset($data->key)) { $tracks['id_nct_str'][] = str_replace([], [], $data->key); } } /* Lấy link bài hát ----------------------------------------------------------------------------------------- */ $element_track_link = 'li a'; foreach ($dom->find($element_track_link) as $data) { if (isset($data->class) && $data->class == 'button_new_window') { $tracks['link'][] = str_replace([], [], $data->href); } } /* Lấy ID dạng số ------------------------------------------------------------------------------------------- */ $element_track_id = 'li span'; foreach ($dom->find($element_track_id) as $data) { if (isset($data->id) && isset($data->class) && $data->class == 'icon_listen') { $tracks['id_nct'][] = str_replace(['NCTCounter_sg_', 'NCTCounter_pn_'], ['', ''], $data->id); } } /* Lấy thời gian của bài hát từ thẻ <meta content="PT3M51S" itemprop="duration" /> -------------------------- */ $element_track_duration = 'li meta'; foreach ($dom->find($element_track_duration) as $data) { if (isset($data->content) && isset($data->itemprop) && $data->itemprop == 'duration') { $duration_str = str_replace(['PT', 'M', 'S'], ['', ':', ''], $data->content); $duration_array = explode(':', $duration_str); if (count($duration_array) == 2) { $tracks['duration'][] = intval($duration_array[0])*60 + intval($duration_array[1]); } else { $tracks['duration'][] = 0; } } } /* Tổng hợp dữ liệu thành mảng ------------------------------------------------------------------------------ */ $result = []; for($i=0; $i < count($tracks['id_nct_str']); $i++) { $result[$i]['id_nct_str'] = $tracks['id_nct_str'][$i]; $result[$i]['id_nct'] = $tracks['id_nct'][$i]; $result[$i]['link'] = $tracks['link'][$i]; $result[$i]['duration'] = $tracks['duration'][$i]; } return $result; } /** * Hàm lấy ds bài hát chưa có ảnh sau khi lấy từ NCT về * * @return array */ public function getNctTrackLinkEmpty() { $query = Track::select(['id', 'link_nct', 'id_zing', 'id_nct', 'id_keeng', 'src_thumbnail_medium']) ->whereNull('art') ->whereNotNull('src_thumbnail_medium'); return $query->get()->toArray(); } public function processNhacVnGetTrackInfoFromTop20($url) { $tracks = []; $dom = getDom($url); /* Lấy ID bài hát ------------------------------------------------------------------------------------------ */ $element_track_id = 'ul li a.addsongtmpl'; foreach ($dom->find($element_track_id) as $data) { $tracks['id'][] = str_replace([], [], $data->id); } /* Lấy tên bài hát ------------------------------------------------------------------------------------------ */ $element_track_title = 'h3.over-text a'; foreach ($dom->find($element_track_title) as $data) { $tracks['title'][] = str_replace([], [], $data->innertext); } /* Lấy đường dẫn ảnh của bài hát ---------------------------------------------------------------------------- */ $element_track_img = 'ul.bxh_song_list li a img'; foreach ($dom->find($element_track_img) as $data) { $tracks['img'][] = str_replace([], [], $data->src); } /* Lấy link bài hát ----------------------------------------------------------------------------------------- */ $element_track_link = 'h3.over-text a'; foreach ($dom->find($element_track_link) as $data) { $link = str_replace([], [], $data->href); $tracks['link'][] = $link; } /* Lấy tên ca sĩ hát ---------------------------------------------------------------------------------------- */ $element_track_singer = 'ul.bxh_song_list li a img'; foreach ($dom->find($element_track_singer) as $data) { $tracks['singer'][] = str_replace([], [], $data->alt); } /* Lấy url thông tin cá nhân ca sĩ -------------------------------------------------------------------------- */ $element_singer_list = 'p.over-text a.singer'; foreach ($dom->find($element_singer_list) as $data) { $tracks['singer_list'][] = [ 'name' => str_replace([], [], $data->innertext), 'url' => str_replace([], [], $data->href) ]; } /* Tổng hợp dữ liệu thành mảng ------------------------------------------------------------------------------ */ $result = []; for($i=0; $i < count($tracks['title']); $i++) { $result[$i]['id_nhacvn'] = $tracks['id'][$i]; $result[$i]['title'] = $tracks['title'][$i]; $result[$i]['img'] = $tracks['img'][$i]; $result[$i]['link'] = $tracks['link'][$i]; $result[$i]['singer'] = $tracks['singer'][$i]; } return $result; } /** * Lấy ds bài hát chưa lấy lượt nghe trong ngày theo từng hệ thống nhạc * Bài nào đã lấy rồi thì sẽ ko lấy nữa * Mỗi lần quét 500 bài cho đến hết * * @param string $src * @param $crawlered * @param int $limit * * @return array */ public function getTrackBySource($src='zing', $crawlered, $limit = Constants::CRAWLER_LISTEN_LIMIT) { $query = Track::select(['id', 'id_zing', 'id_nct', 'id_nhacvn', 'id_keeng', 'title']); if (is_array($crawlered) && count($crawlered) > 0) { $query->whereNotIn('id', $crawlered); } switch ($src) { case 'zing': $query->whereNotNull('id_zing')->where('id_zing', '<>', ''); break; case 'nct': $query->whereNotNull('id_nct')->where('id_nct', '<>', ''); break; case 'nhacvn': $query->whereNotNull('id_nhacvn')->where('id_nhacvn', '<>', ''); break; case 'keeng': $query->whereNotNull('id_keeng')->where('id_keeng', '<>', ''); break; } if ($limit > 0) { $query->take($limit); } return $query->get()->toArray(); } /** * Lấy ds những bài hát đã lấy lượt nghe trong ngày, để lần quét sau sẽ bỏ qua * Mỗi lần quét 300-500 bài trong tracks và bỏ qua những bài đã lấy lượt nghe trong ngày ở bảng crawler_listens * Lấy những bài hát có lượng nghe trong ngày = 0 để cập nhật lại * Có thể tùy biến thêm ($is_update_all): cập nhật toàn bộ hoặc chỉ cập nhập những bài chưa lấy lượt nghe * * @param string $src * @param boolean $is_update_all * * @return array */ public function getCrawlerListenInserted($src='zing', $is_update_all=false) { $min_date = date('Y-m-d 00:00:00'); $max_date = date('Y-m-d 23:59:59'); if ($is_update_all) { $min_date = date('Y-m-d 00:00:00', time() + 86400); $max_date = date('Y-m-d 23:59:59', time() + 86400); } $query = CrawlerListen::select(['id', 'track_id']); switch ($src) { case 'zing': $query->where('zing_crawler_at', '>=', $min_date) ->where('zing_crawler_at', '<=', $max_date) ->where('today_zing', '>' ,0); break; case 'nct': $query->where('nct_crawler_at', '>=', $min_date) ->where('nct_crawler_at', '<=', $max_date) ->where('today_nct', '>' ,0); break; case 'nhacvn': $query->where('nhacvn_crawler_at', '>=', $min_date) ->where('nhacvn_crawler_at', '<=', $max_date) ->where('today_nhacvn', '>' ,0); break; case 'keeng': $query->where('keeng_crawler_at', '>=', $min_date) ->where('keeng_crawler_at', '<=', $max_date) ->where('today_keeng', '>' ,0); break; } $result = $query->get(); return collect($result)->map(function ($item) { return $item->track_id; })->all(); } public function getCrawlerListenNotYetMoved($max_date=null) { if (empty($max_date)) { $max_date = date('Y-m-d 00:00:00'); } else { $max_date = date('Y-m-d 23:59:59', strtotime($max_date)); } return CrawlerListen::select('*') ->where('date_moved_at', '<=', $max_date) ->orWhereNull('date_moved_at') ->take(5000) ->get(); } }