greppr.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <?php
  2. class greppr{
  3. public function __construct(){
  4. include "lib/backend.php";
  5. $this->backend = new backend("greppr");
  6. include "lib/fuckhtml.php";
  7. $this->fuckhtml = new fuckhtml();
  8. }
  9. public function getfilters($page){
  10. return [];
  11. }
  12. private function get($proxy, $url, $get = [], $cookie = false, $post){
  13. $curlproc = curl_init();
  14. curl_setopt($curlproc, CURLOPT_URL, $url);
  15. curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
  16. if($post === false){
  17. if($get !== []){
  18. $get = http_build_query($get);
  19. $url .= "?" . $get;
  20. }
  21. if($cookie === false){
  22. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  23. ["User-Agent: " . config::USER_AGENT,
  24. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
  25. "Accept-Language: en-US,en;q=0.5",
  26. "Accept-Encoding: gzip",
  27. "DNT: 1",
  28. "Connection: keep-alive",
  29. "Upgrade-Insecure-Requests: 1",
  30. "Sec-Fetch-Dest: document",
  31. "Sec-Fetch-Mode: navigate",
  32. "Sec-Fetch-Site: none",
  33. "Sec-Fetch-User: ?1"]
  34. );
  35. }else{
  36. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  37. ["User-Agent: " . config::USER_AGENT,
  38. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  39. "Accept-Language: en-US,en;q=0.5",
  40. "Accept-Encoding: gzip, deflate, br, zstd",
  41. "DNT: 1",
  42. "Sec-GPC: 1",
  43. "Connection: keep-alive",
  44. "Referer: https://greppr.org/search",
  45. "Cookie: PHPSESSID=$cookie",
  46. "Upgrade-Insecure-Requests: 1",
  47. "Sec-Fetch-Dest: document",
  48. "Sec-Fetch-Mode: navigate",
  49. "Sec-Fetch-Site: same-origin",
  50. "Sec-Fetch-User: ?1",
  51. "Priority: u=0, i"]
  52. );
  53. }
  54. }else{
  55. $get = http_build_query($get);
  56. curl_setopt($curlproc, CURLOPT_POST, true);
  57. curl_setopt($curlproc, CURLOPT_POSTFIELDS, $get);
  58. curl_setopt($curlproc, CURLOPT_HTTPHEADER,
  59. ["User-Agent: " . config::USER_AGENT,
  60. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  61. "Accept-Language: en-US,en;q=0.5",
  62. "Accept-Encoding: gzip, deflate, br, zstd",
  63. "Content-Type: application/x-www-form-urlencoded",
  64. "Content-Length: " . strlen($get),
  65. "Origin: https://greppr.org",
  66. "DNT: 1",
  67. "Sec-GPC: 1",
  68. "Connection: keep-alive",
  69. "Referer: https://greppr.org/",
  70. "Cookie: PHPSESSID=$cookie",
  71. "Upgrade-Insecure-Requests: 1",
  72. "Sec-Fetch-Dest: document",
  73. "Sec-Fetch-Mode: navigate",
  74. "Sec-Fetch-Site: same-origin",
  75. "Sec-Fetch-User: ?1",
  76. "Priority: u=0, i"]
  77. );
  78. }
  79. curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
  80. curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
  81. curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
  82. curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
  83. curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
  84. $this->backend->assign_proxy($curlproc, $proxy);
  85. $headers = [];
  86. curl_setopt(
  87. $curlproc,
  88. CURLOPT_HEADERFUNCTION,
  89. function($curlproc, $header) use (&$headers){
  90. $len = strlen($header);
  91. $header = explode(':', $header, 2);
  92. if(count($header) < 2){
  93. // ignore invalid headers
  94. return $len;
  95. }
  96. $headers[strtolower(trim($header[0]))] = trim($header[1]);
  97. return $len;
  98. }
  99. );
  100. $data = curl_exec($curlproc);
  101. if(curl_errno($curlproc)){
  102. throw new Exception(curl_error($curlproc));
  103. }
  104. curl_close($curlproc);
  105. return [
  106. "headers" => $headers,
  107. "data" => $data
  108. ];
  109. }
  110. public function web($get, $first_attempt = true){
  111. if($get["npt"]){
  112. [$q, $proxy] = $this->backend->get($get["npt"], "web");
  113. $tokens = json_decode($q, true);
  114. //
  115. // Get paginated page
  116. //
  117. try{
  118. $html = $this->get(
  119. $proxy,
  120. "https://greppr.org" . $tokens["get"],
  121. [],
  122. $tokens["cookie"],
  123. false
  124. );
  125. }catch(Exception $error){
  126. throw new Exception("Failed to fetch search page");
  127. }
  128. }else{
  129. $search = $get["s"];
  130. if(strlen($search) === 0){
  131. throw new Exception("Search term is empty!");
  132. }
  133. $proxy = $this->backend->get_ip();
  134. //
  135. // get token
  136. //
  137. try{
  138. $html =
  139. $this->get(
  140. $proxy,
  141. "https://greppr.org",
  142. [],
  143. false,
  144. false
  145. );
  146. }catch(Exception $error){
  147. throw new Exception("Failed to fetch search tokens");
  148. }
  149. //
  150. // Parse token
  151. //
  152. $this->fuckhtml->load($html["data"]);
  153. $tokens = [];
  154. $inputs =
  155. $this->fuckhtml
  156. ->getElementsByTagName(
  157. "input"
  158. );
  159. foreach($inputs as $input){
  160. if(!isset($input["attributes"]["name"])){
  161. continue;
  162. }
  163. switch($input["attributes"]["name"]){
  164. case "var1":
  165. case "var2":
  166. case "n":
  167. $tokens[$input["attributes"]["name"]] =
  168. $this->fuckhtml
  169. ->getTextContent(
  170. $input["attributes"]["value"]
  171. );
  172. break;
  173. default:
  174. $tokens["req"] =
  175. $this->fuckhtml
  176. ->getTextContent(
  177. $input["attributes"]["name"]
  178. );
  179. break;
  180. }
  181. }
  182. // get cookie
  183. preg_match(
  184. '/PHPSESSID=([^;]+)/',
  185. $html["headers"]["set-cookie"],
  186. $cookie
  187. );
  188. if(!isset($cookie[1])){
  189. // server sent an unexpected cookie
  190. throw new Exception("Got malformed cookie");
  191. }
  192. $tokens["cookie"] = $cookie[1];
  193. if($tokens === false){
  194. throw new Exception("Failed to grep search tokens");
  195. }
  196. //
  197. // Get initial search page
  198. //
  199. try{
  200. $html = $this->get(
  201. $proxy,
  202. "https://greppr.org/search",
  203. [
  204. "var1" => $tokens["var1"],
  205. "var2" => $tokens["var2"],
  206. $tokens["req"] => $search,
  207. "n" => $tokens["n"]
  208. ],
  209. $tokens["cookie"],
  210. true
  211. );
  212. }catch(Exception $error){
  213. throw new Exception("Failed to fetch search page");
  214. }
  215. }
  216. //$html = file_get_contents("scraper/greppr.html");
  217. //$this->fuckhtml->load($html);
  218. $this->fuckhtml->load($html["data"]);
  219. $out = [
  220. "status" => "ok",
  221. "spelling" => [
  222. "type" => "no_correction",
  223. "using" => null,
  224. "correction" => null
  225. ],
  226. "npt" => null,
  227. "answer" => [],
  228. "web" => [],
  229. "image" => [],
  230. "video" => [],
  231. "news" => [],
  232. "related" => []
  233. ];
  234. // get results for later
  235. $results =
  236. $this->fuckhtml
  237. ->getElementsByClassName(
  238. "result",
  239. "div"
  240. );
  241. // check for next page
  242. $next_elem =
  243. $this->fuckhtml
  244. ->getElementsByClassName(
  245. "pagination",
  246. "ul"
  247. );
  248. if(count($next_elem) !== 0){
  249. $this->fuckhtml->load($next_elem[0]);
  250. $as =
  251. $this->fuckhtml
  252. ->getElementsByClassName(
  253. "page-link",
  254. "a"
  255. );
  256. $break = false;
  257. foreach($as as $a){
  258. if($break === true){
  259. $out["npt"] =
  260. $this->backend->store(
  261. json_encode([
  262. "get" =>
  263. $this->fuckhtml
  264. ->getTextContent(
  265. $a["attributes"]["href"]
  266. ),
  267. "cookie" => $tokens["cookie"]
  268. ]),
  269. "web",
  270. $proxy
  271. );
  272. break;
  273. }
  274. if($a["attributes"]["href"] == "#"){
  275. $break = true;
  276. }
  277. }
  278. }
  279. // scrape results
  280. foreach($results as $result){
  281. $this->fuckhtml->load($result);
  282. $a =
  283. $this->fuckhtml
  284. ->getElementsByTagName(
  285. "a"
  286. )[0];
  287. $description =
  288. $this->fuckhtml
  289. ->getElementsByClassName(
  290. "highlightedDesc",
  291. "p"
  292. );
  293. if(count($description) === 0){
  294. $description = null;
  295. }else{
  296. $description =
  297. $this->limitstrlen(
  298. $this->fuckhtml
  299. ->getTextContent(
  300. $description[0]
  301. )
  302. );
  303. }
  304. $date =
  305. $this->fuckhtml
  306. ->getElementsByTagName(
  307. "p"
  308. );
  309. $date =
  310. strtotime(
  311. explode(
  312. ":",
  313. $this->fuckhtml
  314. ->getTextContent(
  315. $date[count($date) - 1]["innerHTML"]
  316. )
  317. )[1]
  318. );
  319. $out["web"][] = [
  320. "title" =>
  321. $this->fuckhtml
  322. ->getTextContent(
  323. $a["innerHTML"]
  324. ),
  325. "description" => $description,
  326. "url" =>
  327. $this->fuckhtml
  328. ->getTextContent(
  329. $a["attributes"]["href"]
  330. ),
  331. "date" => $date,
  332. "type" => "web",
  333. "thumb" => [
  334. "url" => null,
  335. "ratio" => null
  336. ],
  337. "sublink" => [],
  338. "table" => []
  339. ];
  340. }
  341. return $out;
  342. }
  343. private function limitstrlen($text){
  344. return explode("\n", wordwrap($text, 300, "\n"))[0];
  345. }
  346. }