1
0

naver.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. <?php
  2. class naver{
  3. public function __construct(){
  4. include "lib/backend.php";
  5. $this->backend = new backend("naver");
  6. include "lib/fuckhtml.php";
  7. $this->fuckhtml = new fuckhtml();
  8. }
  9. public function getfilters($page){
  10. $base = [
  11. "time" => [
  12. "display" => "Time",
  13. "option" => [
  14. "any" => "Any time",
  15. "1h" => "Last hour",
  16. "1d" => "Last day",
  17. "1w" => "Last week",
  18. "1m" => "Last month",
  19. "3m" => "Last 3 months",
  20. "6m" => "Last 6 months",
  21. "1y" => "Last year",
  22. ]
  23. ]
  24. ];
  25. switch($page){
  26. case "web":
  27. return
  28. array_merge([
  29. "sort" => [
  30. "display" => "Sort by",
  31. "option" => [
  32. "relevance" => "Relevance", // r
  33. "most_recent" => "Most recent" // dd
  34. ]
  35. ]
  36. ], $base);
  37. break;
  38. case "images":
  39. return
  40. array_merge(
  41. $base,
  42. [
  43. "size" => [
  44. "display" => "Size",
  45. "option" => [
  46. "any" => "Any size",
  47. "highdef" => "High definition" // &res_fr=786432&res_to=100000000
  48. ]
  49. ],
  50. "color" => [ // &color=
  51. "display" => "Color",
  52. "option" => [
  53. "any" => "Any color",
  54. "orange" => "Orange",
  55. "yellow" => "Yellow",
  56. "lime" => "Lime",
  57. "green" => "Green",
  58. "cyan" => "Cyan",
  59. "blue" => "Blue",
  60. "purple" => "Purple",
  61. "pink" => "Pink",
  62. "apricot" => "Apricot",
  63. "ocher" => "Ocher",
  64. "sepia" => "Sepia",
  65. "black" => "Black",
  66. "gray" => "Gray",
  67. "white" => "White"
  68. ]
  69. ],
  70. "license" => [ // &ccl=
  71. "display" => "License",
  72. "option" => [
  73. "any" => "Any license",
  74. "1" => "CCL Total",
  75. "2" => "Commercial use",
  76. "4" => "Modifications permitted"
  77. ]
  78. ]
  79. ]
  80. );
  81. break;
  82. case "videos":
  83. return
  84. [
  85. "time" => [ // done
  86. "display" => "Time",
  87. "option" => [
  88. "any" => "Any time",
  89. "1day" => "Last day",
  90. "1week" => "Last week",
  91. "1month" => "Last month",
  92. "3month" => "Last 3 months",
  93. "6month" => "Last 6 months",
  94. "1year" => "Last year"
  95. ]
  96. ],
  97. "sort" => [ // done
  98. "display" => "Sort by",
  99. "option" => [
  100. "rel" => "Relevance",
  101. "date" => "Most recent", // &sort=date
  102. "playcount" => "Most views", // &sort=playcount
  103. ]
  104. ],
  105. "type" => [ // done
  106. "display" => "Type",
  107. "option" => [
  108. "any" => "Any videos",
  109. "shorts" => "Shorts" // dtype=shorts
  110. ]
  111. ],
  112. "duration" => [
  113. "display" => "Duration", // &playtime=
  114. "option" => [
  115. "any" => "Any duration",
  116. "0:600" => "10 minutes",
  117. "601:1800" => "10-30 minutes",
  118. "1801:3600" => "30-60 minutes",
  119. "3601:65535" => "More than 1 hour"
  120. ]
  121. ]
  122. ];
  123. break;
  124. }
  125. }
  126. private function get($proxy, $url, $get = [], $is_xhr = false){
  127. $curlproc = curl_init();
  128. if($get !== []){
  129. $get = http_build_query($get);
  130. $url .= "?" . $get;
  131. }
  132. curl_setopt($curlproc, CURLOPT_URL, $url);
  133. // use http2
  134. curl_setopt($curlproc, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
  135. curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
  136. if($is_xhr === false){
  137. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  138. ["User-Agent: " . config::USER_AGENT,
  139. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
  140. "Accept-Language: en-US,en;q=0.5",
  141. "Accept-Encoding: gzip",
  142. "DNT: 1",
  143. "Sec-GPC: 1",
  144. "Connection: keep-alive",
  145. "Upgrade-Insecure-Requests: 1",
  146. "Sec-Fetch-Dest: document",
  147. "Sec-Fetch-Mode: navigate",
  148. "Sec-Fetch-Site: same-origin",
  149. "Priority: u=0, i",
  150. "Sec-Fetch-User: ?1"]
  151. );
  152. }else{
  153. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  154. ["User-Agent: " . config::USER_AGENT,
  155. "Accept: */*",
  156. "Accept-Language: en-US,en;q=0.9",
  157. "Accept-Encoding: gzip, deflate, br, zstd",
  158. "Referer: https://search.naver.com/",
  159. "DNT: 1",
  160. "Sec-GPC: 1",
  161. "Alt-Used: s.search.naver.com",
  162. "Connection: keep-alive",
  163. "Sec-Fetch-Dest: script",
  164. "Sec-Fetch-Mode: no-cors",
  165. "Sec-Fetch-Site: same-site",
  166. "TE: trailers"]
  167. );
  168. }
  169. curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
  170. curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
  171. curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
  172. curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
  173. curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
  174. $this->backend->assign_proxy($curlproc, $proxy);
  175. $data = curl_exec($curlproc);
  176. if(curl_errno($curlproc)){
  177. throw new Exception(curl_error($curlproc));
  178. }
  179. curl_close($curlproc);
  180. return $data;
  181. }
  182. public function web($get){
  183. $search = $get["s"];
  184. if(strlen($search) === 0){
  185. throw new Exception("Search term is empty!");
  186. }
  187. $out = [
  188. "status" => "ok",
  189. "spelling" => [
  190. "type" => "no_correction",
  191. "using" => null,
  192. "correction" => null
  193. ],
  194. "npt" => null,
  195. "answer" => [],
  196. "web" => [],
  197. "image" => [],
  198. "video" => [],
  199. "news" => [],
  200. "related" => []
  201. ];
  202. if($get["npt"]){
  203. [$d, $proxy] = $this->backend->get($get["npt"], "web");
  204. try{
  205. $html =
  206. $this->get(
  207. $proxy,
  208. "https://search.naver.com/search.naver" . $d,
  209. []
  210. );
  211. }catch(Exception $error){
  212. throw new Exception("Failed to fetch search page");
  213. }
  214. }else{
  215. // parse filters
  216. // https://search.naver.com
  217. // /search.naver
  218. // ?nso=
  219. // &page=1
  220. // &query=nisekoi
  221. // &sm=tab_pge
  222. // &start=1
  223. // &where=web
  224. $filters = [
  225. "nso" => "",
  226. "query" => $search,
  227. "sm" => "tab_pge",
  228. "where" => "web",
  229. "start" => 1 // increment by number of results each time (16??)
  230. ];
  231. $options = [];
  232. if($get["sort"] != "relevance"){
  233. $options[] = "so:dd";
  234. }
  235. if($get["time"] != "any"){
  236. $options[] = "p:" . $get["time"];
  237. }
  238. if(count($options) !== 0){
  239. $filters["nso"] = implode(",", $options);
  240. }
  241. //$html = file_get_contents("scraper/naver.html");
  242. $proxy = $this->backend->get_ip();
  243. try{
  244. $html =
  245. $this->get(
  246. $proxy,
  247. "https://search.naver.com/search.naver",
  248. $filters
  249. );
  250. }catch(Exception $error){
  251. throw new Exception("Failed to fetch search page");
  252. }
  253. }
  254. $this->fuckhtml->load($html);
  255. $results =
  256. preg_split(
  257. '/entry\.bootstrap\(document\.getElementById\("[a-f0-9-r]+"\), ?/',
  258. $html
  259. );
  260. if(count($results) !== 2){
  261. // this is thrown when no results are found
  262. $nsfw_probe =
  263. $this->fuckhtml
  264. ->getElementsByClassName(
  265. "dsc_adult",
  266. "div"
  267. );
  268. if(count($nsfw_probe) !== 0){
  269. $out["answer"][] = [
  270. "title" => "NSFW results",
  271. "description" => [
  272. [
  273. "type" => "text",
  274. "value" => "Naver blocks logged-out NSFW searches."
  275. ]
  276. ],
  277. "url" => null,
  278. "thumb" => null,
  279. "table" => [],
  280. "sublink" => []
  281. ];
  282. }
  283. return $out;
  284. //throw new Exception("Failed to grep results entrypoint");
  285. }
  286. $json =
  287. json_decode(
  288. $this->fuckhtml
  289. ->extract_json(
  290. $results[1]
  291. ),
  292. true
  293. );
  294. if(!isset($json["body"]["props"]["children"][0]["props"]["children"])){
  295. throw new Exception("Failed to access nested children");
  296. }
  297. foreach($json["body"]["props"]["children"][0]["props"]["children"] as $result){
  298. if(
  299. !isset($result["templateId"]) ||
  300. $result["templateId"] != "webItem"
  301. ){
  302. // should not happen
  303. continue;
  304. }
  305. $result = $result["props"];
  306. // get sublinks
  307. $sublinks = [];
  308. if(isset($result["subLinks"])){
  309. foreach($result["subLinks"] as $s){
  310. $sublinks[] = [
  311. "title" => $s["text"],
  312. "description" => null,
  313. "url" => $s["href"],
  314. "date" => null
  315. ];
  316. }
  317. }
  318. if(isset($result["linkBtns"])){
  319. foreach($result["linkBtns"] as $s){
  320. $sublinks[] = [
  321. "title" => $s["text"],
  322. "description" => null,
  323. "url" => $s["href"],
  324. "date" => null
  325. ];
  326. }
  327. }
  328. // get image (thumbnail, i guess)
  329. if(isset($result["images"][0]["imageSrc"])){
  330. $thumb = [
  331. "ratio" => "16:9",
  332. "url" => $this->unshit_thumb($result["images"][0]["imageSrc"])
  333. ];
  334. }else{
  335. $thumb = [
  336. "ratio" => null,
  337. "url" => null
  338. ];
  339. }
  340. // get table elements
  341. $table = [];
  342. if(isset($result["keyValue"]["contents"])){
  343. foreach($result["keyValue"]["contents"] as $s){
  344. if(!isset($s["valueData"]["text"])){ continue; }
  345. $table[$s["key"]] = $s["valueData"]["text"];
  346. }
  347. }
  348. // get date
  349. $time = null;
  350. if(isset($result["bodyPrefixes"][0]["text"])){
  351. $date =
  352. strtotime(
  353. substr(
  354. $result["bodyPrefixes"][0]["text"],
  355. -1
  356. )
  357. );
  358. if($date !== false){
  359. $time = $date;
  360. }
  361. }
  362. $out["web"][] = [
  363. "title" => $this->decode_html($result["title"]),
  364. "description" => $this->decode_html($result["bodyText"]),
  365. "url" => $result["href"],
  366. "date" => $time,
  367. "type" => "web",
  368. "thumb" => $thumb,
  369. "sublink" => $sublinks,
  370. "table" => $table
  371. ];
  372. }
  373. // get next page
  374. $npt =
  375. $this->fuckhtml
  376. ->getElementsByClassName(
  377. "btn_next",
  378. "a"
  379. );
  380. if(count($npt) !== 0){
  381. $out["npt"] =
  382. $this->backend->store(
  383. $this->fuckhtml
  384. ->getTextContent(
  385. $npt[0]["attributes"]["href"]
  386. ),
  387. "web",
  388. $proxy
  389. );
  390. }
  391. return $out;
  392. }
  393. public function image($get){
  394. $search = $get["s"];
  395. if(strlen($search) === 0){
  396. throw new Exception("Search term is empty!");
  397. }
  398. $out = [
  399. "status" => "ok",
  400. "npt" => null,
  401. "image" => []
  402. ];
  403. if($get["npt"]){
  404. [$url, $proxy] = $this->backend->get($get["npt"], "images");
  405. try{
  406. $json =
  407. $this->get(
  408. $proxy,
  409. $url,
  410. [],
  411. true
  412. );
  413. }catch(Exception $error){
  414. throw new Exception("Failed to fetch search page");
  415. }
  416. }else{
  417. $filters = [
  418. "ac" => "0",
  419. "api_type" => "pc_tab_more",
  420. "aq" => "0",
  421. "display" => 100,
  422. "logStart" => 1,
  423. "mode" => "column",
  424. "nso" => "so:r,p:all",
  425. "nx_search_query" => $search,
  426. "query" => $search,
  427. "section" => "image",
  428. "sm" => "tab_opt",
  429. "ssc" => "tab.image.all",
  430. "start" => 1,
  431. "where" => "image"
  432. // no callback, returns raw json lol
  433. ];
  434. $options = [
  435. "so:r"
  436. ];
  437. if($get["time"] != "any"){
  438. $options[] = "p:" . $get["time"];
  439. }
  440. if(count($options) !== 0){
  441. $filters["nso"] = implode(",", $options);
  442. }
  443. if($get["size"] != "any"){
  444. $filters["res_fr"] = 786432;
  445. $filters["res_to"] = 100000000;
  446. }
  447. if($get["color"] != "any"){
  448. $filters["color"] = $get["color"];
  449. }
  450. if($get["license"] != "any"){
  451. $filters["ccl"] = $get["license"];
  452. }
  453. //$json = file_get_contents("scraper/naver.html");
  454. $proxy = $this->backend->get_ip();
  455. try{
  456. $json =
  457. $this->get(
  458. $proxy,
  459. "https://s.search.naver.com/p/c/image/46/search.naver",
  460. $filters,
  461. true
  462. );
  463. }catch(Exception $error){
  464. throw new Exception("Failed to fetch search page");
  465. }
  466. }
  467. $json = json_decode($json, true);
  468. if($json === null){
  469. throw new Exception("Failed to decode JSON");
  470. }
  471. if(!isset($json["items"])){
  472. // no results returned :(
  473. return $out;
  474. //throw new Exception("Naver did not return an items object");
  475. }
  476. foreach($json["items"] as $image){
  477. // why does it fucking do that
  478. if($image["orgWidth"] === 0){ continue; }
  479. $out["image"][] = [
  480. "title" => trim($image["title"], "."),
  481. "source" => [
  482. [
  483. "url" => $image["originalUrl"],
  484. "width" => (int)$image["orgWidth"],
  485. "height" => (int)$image["orgHeight"]
  486. ],
  487. [
  488. "url" => $image["thumb"],
  489. "width" => (int)$image["thumbWidth"],
  490. "height" => (int)$image["thumbHeight"]
  491. ]
  492. ],
  493. "url" => $image["link"]
  494. ];
  495. }
  496. // get npt
  497. if(
  498. isset($json["url"]) &&
  499. $json["url"] != "" &&
  500. $json["url"] != null
  501. ){
  502. $out["npt"] =
  503. $this->backend->store(
  504. $json["url"],
  505. "images",
  506. $proxy
  507. );
  508. }
  509. return $out;
  510. }
  511. public function video($get){
  512. $search = $get["s"];
  513. if(strlen($search) === 0){
  514. throw new Exception("Search term is empty!");
  515. }
  516. $out = [
  517. "status" => "ok",
  518. "npt" => null,
  519. "video" => [],
  520. "author" => [],
  521. "livestream" => [],
  522. "playlist" => [],
  523. "reel" => []
  524. ];
  525. if($get["npt"]){
  526. [$url, $proxy] = $this->backend->get($get["npt"], "images");
  527. try{
  528. $json =
  529. $this->get(
  530. $proxy,
  531. $url,
  532. [],
  533. true
  534. );
  535. }catch(Exception $error){
  536. throw new Exception("Failed to fetch search page");
  537. }
  538. }else{
  539. // https://s.search.naver.com/p/video/48/search.naver?ac=0&aq=0&crbase=63&display=48&dtype=&last_block_type=recom&nlu_query=&nq=&nqx_theme={"theme":{"main":{"name":"encyclopedia","source":"TOS"}}}&nx_and_query=&nx_search_hlquery=&nx_search_query=&nx_sub_query=&page=2&period=&playtime=&ptype=&query=asmr&selected_channel=&selected_cp=&sm=mtb_pge&sort=rel&ssc=tab.video.all&start=49&video_more=1
  540. // https://s.search.naver.com/p/video/48/search.naver
  541. // ?ac=0
  542. // &aq=0
  543. // &crbase=63
  544. // &display=48
  545. // &dtype=
  546. // &last_block_type=recom
  547. // &nlu_query=
  548. // &nq=
  549. // &nqx_theme={"theme":{"main":{"name":"encyclopedia","source":"TOS"}}}
  550. // &nx_and_query=
  551. // &nx_search_hlquery=
  552. // &nx_search_query=
  553. // &nx_sub_query=
  554. // &page=2
  555. // &period=
  556. // &playtime=
  557. // &ptype=
  558. // &query=asmr
  559. // &selected_channel=
  560. // &selected_cp=
  561. // &sm=mtb_pge
  562. // &sort=rel
  563. // &ssc=tab.video.all
  564. // &start=49
  565. // &video_more=1
  566. $filters = [
  567. "ac" => "0",
  568. "aq" => "0",
  569. "crbase" => "78",
  570. "display" => 48,
  571. "dtype" => "",
  572. "last_block_type" => "recom",
  573. "nlu_query" => "",
  574. "nq" => "",
  575. "nx_and_query" => "",
  576. "nx_search_hlquery" => "",
  577. "nx_search_query" => "",
  578. "nx_sub_query" => "",
  579. "page" => 1,
  580. "period" => "",
  581. "playtime" => "",
  582. "ptype" => "",
  583. "query" => $search,
  584. "selected_channel" => "",
  585. "selected_cp" => "",
  586. "sm" => "mtb_pge",
  587. "sort" => "rel",
  588. "ssc" => "tab.video.all",
  589. "start" => 1,
  590. "video_more" => 1
  591. ];
  592. if($get["type"] != "any"){
  593. $filters["dtype"] = $get["type"];
  594. }
  595. if($get["time"] != "any"){
  596. $filters["period"] = $get["time"];
  597. }
  598. if($get["sort"] != "rel"){
  599. $filters["sort"] = $get["sort"];
  600. }
  601. if($get["duration"] != "any"){
  602. $filters["playtime"] = $get["duration"];
  603. }
  604. //$json = file_get_contents("scraper/naver.html");
  605. $proxy = $this->backend->get_ip();
  606. try{
  607. $json =
  608. $this->get(
  609. $proxy,
  610. "https://s.search.naver.com/p/video/48/search.naver",
  611. $filters,
  612. true
  613. );
  614. }catch(Exception $error){
  615. throw new Exception("Failed to fetch search page");
  616. }
  617. }
  618. $json = json_decode($json, true);
  619. if($json === null){
  620. throw new Exception("Failed to decode JSON");
  621. }
  622. if(!isset($json["collection"])){
  623. return $out;
  624. //throw new Exception("Naver did not return a collection HTML element");
  625. }
  626. foreach($json["collection"] as $snippet){
  627. if(!isset($snippet["html"])){ continue; }
  628. $this->fuckhtml->load($snippet["html"]);
  629. $div =
  630. $this->fuckhtml
  631. ->getElementsByTagName(
  632. "div"
  633. );
  634. $items =
  635. $this->fuckhtml
  636. ->getElementsByAttributeValue(
  637. "data-template-id",
  638. "videoItem",
  639. $div
  640. );
  641. // parse normal videos
  642. foreach($items as $item){
  643. if($item["level"] === 6){ continue; }
  644. $this->fuckhtml->load($item);
  645. // get url
  646. $as =
  647. $this->fuckhtml
  648. ->getElementsByAttributeName(
  649. "data-heatmap-target",
  650. "a"
  651. );
  652. if(count($as) === 0){
  653. // should not happen
  654. continue;
  655. }
  656. // get thumbnail
  657. $thumb =
  658. $this->fuckhtml
  659. ->getElementsByAttributeValue(
  660. "loading",
  661. "lazy",
  662. "img"
  663. );
  664. if(count($thumb) !== 0){
  665. $thumb = [
  666. "url" =>
  667. $this->unshit_thumb(
  668. $this->fuckhtml
  669. ->getTextContent(
  670. $thumb[0]["attributes"]["src"]
  671. )
  672. ),
  673. "ratio" => "16:9"
  674. ];
  675. }else{
  676. $thumb = [
  677. "url" => null,
  678. "ratio" => null
  679. ];
  680. }
  681. // get timestamp
  682. $timestamp_probe =
  683. $this->fuckhtml
  684. ->getElementsByClassName(
  685. "sds-comps-text-type-footnote",
  686. "span"
  687. );
  688. if(count($timestamp_probe) !== 0){
  689. $timestamp =
  690. $this->hms2int(
  691. $this->fuckhtml
  692. ->getTextContent(
  693. $timestamp_probe[0]
  694. )
  695. );
  696. }else{
  697. $timestamp = null;
  698. }
  699. $out["video"][] = [
  700. "title" =>
  701. $this->fuckhtml
  702. ->getTextContent(
  703. $as[0]
  704. ),
  705. "description" => null,
  706. "author" => [
  707. "name" =>
  708. isset($item["attributes"]["profileimagealt"]) ?
  709. $this->fuckhtml
  710. ->getTextContent(
  711. $item["attributes"]["profileimagealt"]
  712. ) : null,
  713. "url" =>
  714. isset($item["attributes"]["profileimagehref"]) ?
  715. $this->fuckhtml
  716. ->getTextContent(
  717. $item["attributes"]["profileimagehref"]
  718. ) : null,
  719. "avatar" =>
  720. isset($item["attributes"]["profileimagesrc"]) ?
  721. $this->fuckhtml
  722. ->getTextContent(
  723. $item["attributes"]["profileimagesrc"]
  724. ) : null
  725. ],
  726. "date" => null,
  727. "duration" => $timestamp,
  728. "views" => null,
  729. "thumb" => $thumb,
  730. "url" =>
  731. $this->fuckhtml
  732. ->getTextContent(
  733. $as[0]["attributes"]["href"]
  734. )
  735. ];
  736. }
  737. // reset
  738. $this->fuckhtml->load($snippet["html"]);
  739. // parse reels
  740. $carousels =
  741. array_merge(
  742. $this->fuckhtml // for the reels only tab
  743. ->getElementsByClassName(
  744. "fds-video-tab-shortform-desk-filter",
  745. $div
  746. ),
  747. $this->fuckhtml // for the normal tab with reels inbetween
  748. ->getElementsByClassName(
  749. "fds-video-tab-shortform-desk",
  750. $div
  751. )
  752. );
  753. foreach($carousels as $carousel){
  754. $this->fuckhtml->load($carousel);
  755. $as =
  756. $this->fuckhtml
  757. ->getElementsByTagName(
  758. "a"
  759. );
  760. foreach($as as $reel){
  761. $this->fuckhtml->load($reel);
  762. $spans =
  763. $this->fuckhtml
  764. ->getElementsByTagName(
  765. "span"
  766. );
  767. $title =
  768. $this->fuckhtml
  769. ->getTextContent(
  770. $spans[0]
  771. );
  772. // get thumbnail
  773. $thumb =
  774. $this->fuckhtml
  775. ->getElementsByAttributeValue(
  776. "loading",
  777. "lazy",
  778. "img"
  779. );
  780. if(count($thumb) !== 0){
  781. $thumb = [
  782. "url" =>
  783. $this->unshit_thumb(
  784. $this->fuckhtml
  785. ->getTextContent(
  786. $thumb[0]["attributes"]["src"]
  787. )
  788. ),
  789. "ratio" => "16:9"
  790. ];
  791. }else{
  792. $thumb = [
  793. "url" => null,
  794. "ratio" => null
  795. ];
  796. }
  797. $name =
  798. $this->fuckhtml
  799. ->getElementsByClassName(
  800. "sds-comps-profile-info-title-text",
  801. $spans
  802. );
  803. if(count($name) === 0){
  804. $name = null;
  805. }else{
  806. $name =
  807. $this->fuckhtml
  808. ->getTextContent(
  809. $name[0]
  810. );
  811. }
  812. $out["reel"][] = [
  813. "title" => $title,
  814. "description" => null,
  815. "author" => [
  816. "name" => $name,
  817. "url" => null,
  818. "avatar" => null
  819. ],
  820. "date" => null,
  821. "duration" => null,
  822. "views" => null,
  823. "thumb" => $thumb,
  824. "url" =>
  825. $this->fuckhtml
  826. ->getTextContent(
  827. $reel["attributes"]["href"]
  828. )
  829. ];
  830. }
  831. }
  832. }
  833. // get npt
  834. if(
  835. isset($json["url"]) &&
  836. $json["url"] != "" &&
  837. $json["url"] != null
  838. ){
  839. $out["npt"] =
  840. $this->backend->store(
  841. $json["url"],
  842. "images",
  843. $proxy
  844. );
  845. }
  846. return $out;
  847. }
  848. private function unshit_thumb($url){
  849. $parts = parse_url($url);
  850. if($parts["host"] == "search.pstatic.net"){
  851. parse_str($parts["query"], $str);
  852. if(isset($str["src"])){
  853. return $str["src"];
  854. }
  855. }
  856. return $url;
  857. }
  858. private function decode_html($html){
  859. return
  860. trim(
  861. html_entity_decode(
  862. strip_tags(
  863. $html
  864. )
  865. ),
  866. "."
  867. );
  868. }
  869. private function hms2int($time){
  870. $parts = explode(":", $time, 3);
  871. $time = 0;
  872. if(count($parts) === 3){
  873. // hours
  874. $time = $time + ((int)$parts[0] * 3600);
  875. array_shift($parts);
  876. }
  877. if(count($parts) === 2){
  878. // minutes
  879. $time = $time + ((int)$parts[0] * 60);
  880. array_shift($parts);
  881. }
  882. // seconds
  883. $time = $time + (int)$parts[0];
  884. return $time;
  885. }
  886. }