RuTrackerに基づいて独自のトレント検索エンジンを実行する方法は?

「水」を使わずに、できる限り書くようにします。 最小限の不必要な注意散漫な情報と暴言。 最大の有用な情報と作業コード。 RuTrackerに基づいた独自のトレント検索エンジンが必要な理由については疑問を投げかけません。 そして、私は自分をプログラミングの第一人者とは考えていません。 このサイトを一緒に作成します。 Apache + PHP、MySQL、Sphinxを使用します。 最小限の共有ホスティングでは、サイトがすぐに機能しないことをすぐに警告します。



画像



データベース



まず、ベース自体を取得する必要があります。 RuTrackerは毎月ここでトレントをダンプします 。 2ダースのCSVファイルをダウンロードして展開します。



画像



トレントに関する情報を持っているものだけが必要です。残りは削除されます。 ファイル「category_info.csv」-各ファイルを開きたくない人のためのヒント(削除:「category_1.csv」、「category_4.csv」、「category_36.csv」)。 残りのファイルを開いて、そのような構造を確認します(「;」文字をすぐに新しい行に置き換えました。これは視覚的に便利です)。

「1568」 RuTrackerのセクションID
「料理」 セクションタイトル
「63629」 RuTrackerのトピックID
「F7D7BE97A818CCDFA072C42348EB669F7883888D」 ハッシュトレント
「(料理)おいしい物語1」 トレント名
「729927066」 バイト単位の配信サイズ
2006-08-21 10:00:22 配布日


次に、すべての情報をデータベースに追加します。 MySQLを最も一般的なデータベースとして使用します。 ここにそのようなテーブルがあります(注:ハッシュ列は一意であり、すべてのテキストデータはutf8エンコーディングです):



SQLテーブル
CREATE TABLE IF NOT EXISTS `torrents` ( `id` int(11) NOT NULL, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `hash` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `date` date NOT NULL, `size` int(11) NOT NULL, `topic_id` int(11) NOT NULL, `cat_id` int(11) NOT NULL, `cat_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_bin; ALTER TABLE `torrents` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `hash` (`hash`); ALTER TABLE `torrents` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
      
      







次に、サーバー上のすべてのCSVファイルを1つのフォルダーにアップロードします(たとえば、「db」と呼びます)。 以下に示す簡単なスクリプトを使用して、トレントに関する情報をデータベースに追加できます。 また、ソースCSVファイルと同じフォルダーにアップロードする必要があります。



ファイルinsert_to_db.php
 <? //    3-  set_time_limit(180); //  MySQL,     mysql_connect("localhost", "torrent", "password") or die("Could not connect to MySQL"); // ,     mysql_select_db("torrent") or die("Could not select database"); //       utf8 mysql_query("SET NAMES utf8"); //    url  "f" $fp = fopen($_GET[f], "r"); //       while (!feof($fp)) { //  (,  trim()   ,      "") $tmp = trim(fgets($fp)); //   .    ";" $torrent = explode('";"', $tmp); //        " $torrent[0] = substr($torrent[0], 1); $torrent[6] = substr($torrent[6], 0, (strlen($torrent[6]) - 1)); //   ,          //print '<pre>'; print_r($torrent); exit(); //      mysql_query("INSERT INTO `torrents` (`name`, `hash`, `date`, `size`, `topic_id`, `cat_id`, `cat_name`) VALUES ('" . mysql_real_escape_string($torrent[4]) . "', '" . $torrent[3] . "', '" . $torrent[6] . "', '" . $torrent[5] . "', '" . $torrent[2] . "', '" . $torrent[0] . "', '" . mysql_real_escape_string($torrent[1]) . "') "); } //  fclose($fp); //     print 'complete: ' . $_GET[f]; ?>
      
      







ブラウザを開き、URL「http://site.ru/db/insert_to_db.php?f=category_10.csv」を開きます。 各CSVファイルについても同じことを行います。 はい、これはすべて自動化できますが、すべてができる限り明確になるように具体的に書きました。 これらのアクションの後、160万件を超えるレコードがテーブルに表示されました。 小さなベースではありません。 この量のデータを使用したMySQL検索では処理できないため、このタスクをSphinxに任せましょう。



画像



スフィンクス



Sphinxのさまざまなシステムへのインストールは、さまざまな方法で行われます。 それはすべて、オペレーティングシステムとハードウェアに依存します。 このトピックは別の記事に値します。 しかし、インターネットには非常に多くの優れたマニュアルがあります。 ロシア語でも。 次に、Sphinxの構成ファイルをセットアップします。 キャッシュなど、サイトのルートディレクトリにディレクトリを作成します。 サイトのすべてのSphinxインデックスファイルはここに保存されます。 構成ファイルをこのフォルダーにロードします(リストを以下に示します)。



Torrents.confファイル
 #      source torrentz { #    type = mysql sql_host = localhost sql_user = torrent sql_pass = password sql_db = torrent sql_port = 3306 #        utf8 sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 #     sql_query = SELECT id, name FROM torrents #  ( )     .       sql_ranged_throttle = 0 } #  .       Sphinx index torrentz { #   source = torrentz #     path = /home/rutr/rutracker.online/www/cache/ #    docinfo = extern #      morphology = stem_enru #     min_word_len = 2 #   charset_type = utf-8 #  charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F #    min_infix_len = 2 #    "*" enable_star = 1 } #   indexer { #     mem_limit = 32M } #    searchd { #           listen = 127.0.0.1:3312 #  log = /home/rutr/rutracker.online/www/cache/searchd.log #   query_log = /home/rutr/rutracker.online/www/cache/query.log #      read_timeout = 5 #  -    max_children = 30 #   pid- pid_file = /home/rutr/rutracker.online/www/cache/searchd.pid #  -   max_matches = 1000 }
      
      







sshを介してサーバーに接続します。 Sphinxがデータベースを検索できるようにするには、インデックスを準備する必要があります。 コマンドを実行します。



 indexer --config /home/rutr/rutracker.online/www/cache/torrents.conf –all
      
      





Sphinxはしばらくの間、データベースインデックスをホストします。 期間はサーバーの容量に依存します。 私の場合、インデックス作成には約10分かかりました。



画像



インデックス作成の終了後、すべてがうまくいったかどうかをチェックします。 これを行うには、次のコマンドを使用してコンソールで検索を実行します(検索フレーズは、構成ファイルを指定した後に書き込まれます)。



 search --config /home/rutr/rutracker.online/www/cache/torrents.conf morrowind mod
      
      





画像



上のスクリーンショットに似たものを見たら、インデックス作成は成功しました。 何も見つからない場合は、次のコマンドを実行する必要はありません。 Sphinx検索デーモンを起動するには、次のコマンドを実行します。



 searchd --config /home/rutr/rutracker.online/www/cache/torrents.conf
      
      





画像



再起動するたびにデーモンを起動する必要があることに注意してください。 デーモンをオフにするには(必要な場合)、上記のコマンドの最後に「--stop」を追加します。



Web



Webインターフェースに使用するフレームワークについては考えていませんでした。 要件は単純です。使いやすさ、レスポンシブデザイン、最新のすべてのブラウザーのサポートです。 この下では、Bootstrapが少し退屈ですが、素晴らしいです。 配布キットをダウンロードする必要はなく、スタイルシートをオンラインで接続できます。 メインページはPHPを使用しない純粋なHTMLです。 コードへのコメントは不要だと思います。



Index.phpファイル
 <!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/favicon.ico"> <title>  RuTracker</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> <style type="text/css"> .inCenter { margin: auto; position: absolute; top: 0; left: 0; bottom: 0; right: 0; } .inCenter.isResp { width: 50%; height: 50%; min-width: 400px; max-width: 800px; padding: 40px; } </style> </head> <body> <div class="container"> <div class="row"> <div class="inCenter isResp"> <div class="col-sm-12 col-md-10 col-md-offset-1"> <form action="search.php" method="GET"> <div class="form-group text-center"> <h1>  RuTracker</h1> </div> <div class="form-group input-group"> <input class="form-control input-lg" type="text" name="q" placeholder=""/> <span class="input-group-btn"> <button class="btn btn-primary input-lg" type="submit"><i class="glyphicon glyphicon-search"></i></button> </span> </div> </form> </div> </div> </div> </div> </body> </html>
      
      



= "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"整合性= "sha384-1q8mTJOASx8j1Au + a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin = "匿名"> <!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/favicon.ico"> <title> RuTracker</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> <style type="text/css"> .inCenter { margin: auto; position: absolute; top: 0; left: 0; bottom: 0; right: 0; } .inCenter.isResp { width: 50%; height: 50%; min-width: 400px; max-width: 800px; padding: 40px; } </style> </head> <body> <div class="container"> <div class="row"> <div class="inCenter isResp"> <div class="col-sm-12 col-md-10 col-md-offset-1"> <form action="search.php" method="GET"> <div class="form-group text-center"> <h1> RuTracker</h1> </div> <div class="form-group input-group"> <input class="form-control input-lg" type="text" name="q" placeholder=""/> <span class="input-group-btn"> <button class="btn btn-primary input-lg" type="submit"><i class="glyphicon glyphicon-search"></i></button> </span> </div> </form> </div> </div> </div> </div> </body> </html>







メインページのデザインは、非常に最小限で機能的なものであることがわかりました。



画像



検索スクリプトはさらに興味深いものになります。 まず、PHPのSphinx APIが必要です。 最新バージョンはこちらから入手できます 。 検索スクリプトがどのように機能するか、リストでさらに説明します。 ファイルを接続してAPIを操作し、検索を構成し、検索し、検索結果を便利な形式で投稿します。 追加のクリックなしで、検索からトレントを直接ダウンロードできます。



ファイルsearch.php
 <? //    $q=trim(urldecode($_GET[q])); //    ,       if (empty($q)) {header("Location: /"); exit();} //  , ... //  MySQL,     mysql_connect("localhost", "torrent", "password") or die("Could not connect to MySQL"); // ,     mysql_select_db("torrent") or die("Could not select database"); //       utf8 mysql_query("SET NAMES utf8"); // API Sphinx include("sphinxapi.php"); //  Sphinx $sphinx=new SphinxClient(); //  Sphinx-.      "torrents.conf" $sphinx->SetServer('localhost', 3312); //     $sphinx->SetMatchMode(SPH_MATCH_ANY); //    $sphinx->SetSortMode(SPH_SORT_RELEVANCE); // 50    . $sphinx->SetLimits(0, 50); //  (* -      "torrents.conf",     : torrentz) $torrents=$sphinx->Query($q, '*'); //    ,         //print $sphinx->getLastError(); //print '<br><pre>'; print_r($torrents); exit(); //    ,   .   .       -  . function bytesToSize($bytes, $precision = 0) { $kilobyte = 1024; $megabyte = $kilobyte * 1024; $gigabyte = $megabyte * 1024; $terabyte = $gigabyte * 1024; if (($bytes >= 0) && ($bytes < $kilobyte)) {return $bytes . ' B';} elseif (($bytes >= $kilobyte) && ($bytes < $megabyte)) {return round($bytes / $kilobyte, $precision) . ' Kb';} elseif (($bytes >= $megabyte) && ($bytes < $gigabyte)) {return round($bytes / $megabyte, $precision) . ' Mb';} elseif (($bytes >= $gigabyte) && ($bytes < $terabyte)) {return round($bytes / $gigabyte, $precision) . ' Gb';} elseif ($bytes >= $terabyte) {return round($bytes / $terabyte, $precision) . ' Tb';} else {return $bytes . ' B';} } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/favicon.ico"> <title><?=htmlspecialchars($q)?></title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> <style type="text/css"> body { padding-top: 80px; padding-bottom: 20px; } </style> </head> <body> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/">  RuTracker</a> </div> <div id="navbar" class="navbar-collapse collapse"> <form action="/search.php" method="GET" class="navbar-form navbar-left"> <div class="form-group input-group"> <input type="text" placeholder="" value="<?=htmlspecialchars($q)?>" class="form-control" name="q"> <span class="input-group-btn"> <button class="btn btn-primary" type="submit"><i class="glyphicon glyphicon-search"></i></button> </span> </div> </form> </div> <!--/.navbar-collapse --> </div> </nav> <div class="container"> <h1><?=htmlspecialchars($q)?></h1> <table class="table table-striped"> <caption> : <?=$torrents[total_found]?></caption> <tbody> <? //         $ids = array_keys($torrents[matches]); //   id-     SQL  $ids = implode(',', $ids); // SQL        $sql="SELECT `id`, `name`, `hash`, `date`, `size` FROM `torrents` WHERE `id` IN (".$ids.") ORDER BY FIELD(`id`, ".$ids.")"; // SQL  $r=mysql_query($sql); //   for ($i=0; $i < mysql_num_rows($r); $i++) { //      $f=mysql_fetch_array($r); //     $torrent_date=explode('-', $f[date]); //   ,      $torrent_date=$torrent_date[2].'.'.$torrent_date[1].'.'.$torrent_date[0]; ?> <tr> <td width="75%"><a href="/torrent.php?id=<?=$f[id]?>"><?=$f[name]?></a></td> <td width="5%"><a href="magnet:?xt=urn:btih:<?=$f[hash]?>"><i class="glyphicon glyphicon-magnet"></i></a></td> <td width="10%"><?=bytesToSize($f[size])?></td> <td width="10%"><?=$torrent_date?></td> </tr> <? } ?> </tbody> </table> </div> <!-- /.container --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script> </body> </html>
      
      



= "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"整合性= "sha384-1q8mTJOASx8j1Au + a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin = "匿名"> <? // $q=trim(urldecode($_GET[q])); // , if (empty($q)) {header("Location: /"); exit();} // , ... // MySQL, mysql_connect("localhost", "torrent", "password") or die("Could not connect to MySQL"); // , mysql_select_db("torrent") or die("Could not select database"); // utf8 mysql_query("SET NAMES utf8"); // API Sphinx include("sphinxapi.php"); // Sphinx $sphinx=new SphinxClient(); // Sphinx-. "torrents.conf" $sphinx->SetServer('localhost', 3312); // $sphinx->SetMatchMode(SPH_MATCH_ANY); // $sphinx->SetSortMode(SPH_SORT_RELEVANCE); // 50 . $sphinx->SetLimits(0, 50); // (* - "torrents.conf", : torrentz) $torrents=$sphinx->Query($q, '*'); // , //print $sphinx->getLastError(); //print '<br><pre>'; print_r($torrents); exit(); // , . . - . function bytesToSize($bytes, $precision = 0) { $kilobyte = 1024; $megabyte = $kilobyte * 1024; $gigabyte = $megabyte * 1024; $terabyte = $gigabyte * 1024; if (($bytes >= 0) && ($bytes < $kilobyte)) {return $bytes . ' B';} elseif (($bytes >= $kilobyte) && ($bytes < $megabyte)) {return round($bytes / $kilobyte, $precision) . ' Kb';} elseif (($bytes >= $megabyte) && ($bytes < $gigabyte)) {return round($bytes / $megabyte, $precision) . ' Mb';} elseif (($bytes >= $gigabyte) && ($bytes < $terabyte)) {return round($bytes / $gigabyte, $precision) . ' Gb';} elseif ($bytes >= $terabyte) {return round($bytes / $terabyte, $precision) . ' Tb';} else {return $bytes . ' B';} } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/favicon.ico"> <title><?=htmlspecialchars($q)?></title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> <style type="text/css"> body { padding-top: 80px; padding-bottom: 20px; } </style> </head> <body> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/"> RuTracker</a> </div> <div id="navbar" class="navbar-collapse collapse"> <form action="/search.php" method="GET" class="navbar-form navbar-left"> <div class="form-group input-group"> <input type="text" placeholder="" value="<?=htmlspecialchars($q)?>" class="form-control" name="q"> <span class="input-group-btn"> <button class="btn btn-primary" type="submit"><i class="glyphicon glyphicon-search"></i></button> </span> </div> </form> </div> <!--/.navbar-collapse --> </div> </nav> <div class="container"> <h1><?=htmlspecialchars($q)?></h1> <table class="table table-striped"> <caption> : <?=$torrents[total_found]?></caption> <tbody> <? // $ids = array_keys($torrents[matches]); // id- SQL $ids = implode(',', $ids); // SQL $sql="SELECT `id`, `name`, `hash`, `date`, `size` FROM `torrents` WHERE `id` IN (".$ids.") ORDER BY FIELD(`id`, ".$ids.")"; // SQL $r=mysql_query($sql); // for ($i=0; $i < mysql_num_rows($r); $i++) { // $f=mysql_fetch_array($r); // $torrent_date=explode('-', $f[date]); // , $torrent_date=$torrent_date[2].'.'.$torrent_date[1].'.'.$torrent_date[0]; ?> <tr> <td width="75%"><a href="/torrent.php?id=<?=$f[id]?>"><?=$f[name]?></a></td> <td width="5%"><a href="magnet:?xt=urn:btih:<?=$f[hash]?>"><i class="glyphicon glyphicon-magnet"></i></a></td> <td width="10%"><?=bytesToSize($f[size])?></td> <td width="10%"><?=$torrent_date?></td> </tr> <? } ?> </tbody> </table> </div> <!-- /.container --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script> </body> </html>







ユーザーの利便性のために、各トレントに対して個別のページを作成します。 突然誰かがリンクを送信する必要があります。



torrent.phpファイル
 <? //   id  $id=trim(urldecode($_GET[id])); //  id,       if (empty($id)) {header("Location: /"); exit();} // id , ... //  MySQL,     mysql_connect("localhost", "torrent", "password") or die("Could not connect to MySQL"); // ,     mysql_select_db("torrent") or die("Could not select database"); //       utf8 mysql_query("SET NAMES utf8"); // SQL      id $sql="SELECT * FROM `torrents` WHERE `id`='".mysql_real_escape_string($id)."'"; // SQL  $r=mysql_query($sql); //   id  ,       if (mysql_num_rows($r)==0) {header("Location: /"); exit();} //     $torrent=mysql_fetch_array($r); //     $torrent_date=explode('-', $torrent[date]); $torrent_date=$torrent_date[2].'.'.$torrent_date[1].'.'.$torrent_date[0]; //    ,   .   .       -  . function bytesToSize($bytes, $precision = 0) { $kilobyte = 1024; $megabyte = $kilobyte * 1024; $gigabyte = $megabyte * 1024; $terabyte = $gigabyte * 1024; if (($bytes >= 0) && ($bytes < $kilobyte)) {return $bytes . ' B';} elseif (($bytes >= $kilobyte) && ($bytes < $megabyte)) {return round($bytes / $kilobyte, $precision) . ' Kb';} elseif (($bytes >= $megabyte) && ($bytes < $gigabyte)) {return round($bytes / $megabyte, $precision) . ' Mb';} elseif (($bytes >= $gigabyte) && ($bytes < $terabyte)) {return round($bytes / $gigabyte, $precision) . ' Gb';} elseif ($bytes >= $terabyte) {return round($bytes / $terabyte, $precision) . ' Tb';} else {return $bytes . ' B';} } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/favicon.ico"> <title><?=htmlspecialchars($torrent[name])?></title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> <style type="text/css"> body { padding-top: 80px; padding-bottom: 20px; } </style> </head> <body> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/">  RuTracker</a> </div> <div id="navbar" class="navbar-collapse collapse"> <form action="/search.php" method="GET" class="navbar-form navbar-left"> <div class="form-group input-group"> <input type="text" placeholder="" value="" class="form-control" name="q"> <span class="input-group-btn"> <button class="btn btn-primary" type="submit"><i class="glyphicon glyphicon-search"></i></button> </span> </div> </form> </div> <!--/.navbar-collapse --> </div> </nav> <div class="container"> <h1><?=htmlspecialchars($torrent[name])?></h1> <table class="table table-striped"> <tbody> <tr> <th width="20%">:</th> <td><a href="magnet:?xt=urn:btih:<?=$torrent[hash]?>"><i class="glyphicon glyphicon-magnet"></i> Magnet</a></td> </tr> <tr> <th width="20%">:</th> <td><?=bytesToSize($torrent[size])?></td> </tr> <tr> <th width="20%"> :</th> <td><?=$torrent_date?></td> </tr> <tr> <th width="20%">:</th> <td><a target=_blank href="http://rutracker.org/forum/viewforum.php?f=<?=$torrent[cat_id]?>"><?=htmlspecialchars($torrent[cat_name])?></a></td> </tr> <tr> <th width="20%">:</th> <td><a target=_blank href="http://rutracker.org/forum/viewtopic.php?t=<?=$torrent[topic_id]?>"> #<?=$torrent[topic_id]?></a></td> </tr> </tbody> </table> </div> <!-- /.container --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script> </body> </html>
      
      



= "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"整合性= "sha384-1q8mTJOASx8j1Au + a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin = "匿名"> <? // id $id=trim(urldecode($_GET[id])); // id, if (empty($id)) {header("Location: /"); exit();} // id , ... // MySQL, mysql_connect("localhost", "torrent", "password") or die("Could not connect to MySQL"); // , mysql_select_db("torrent") or die("Could not select database"); // utf8 mysql_query("SET NAMES utf8"); // SQL id $sql="SELECT * FROM `torrents` WHERE `id`='".mysql_real_escape_string($id)."'"; // SQL $r=mysql_query($sql); // id , if (mysql_num_rows($r)==0) {header("Location: /"); exit();} // $torrent=mysql_fetch_array($r); // $torrent_date=explode('-', $torrent[date]); $torrent_date=$torrent_date[2].'.'.$torrent_date[1].'.'.$torrent_date[0]; // , . . - . function bytesToSize($bytes, $precision = 0) { $kilobyte = 1024; $megabyte = $kilobyte * 1024; $gigabyte = $megabyte * 1024; $terabyte = $gigabyte * 1024; if (($bytes >= 0) && ($bytes < $kilobyte)) {return $bytes . ' B';} elseif (($bytes >= $kilobyte) && ($bytes < $megabyte)) {return round($bytes / $kilobyte, $precision) . ' Kb';} elseif (($bytes >= $megabyte) && ($bytes < $gigabyte)) {return round($bytes / $megabyte, $precision) . ' Mb';} elseif (($bytes >= $gigabyte) && ($bytes < $terabyte)) {return round($bytes / $gigabyte, $precision) . ' Gb';} elseif ($bytes >= $terabyte) {return round($bytes / $terabyte, $precision) . ' Tb';} else {return $bytes . ' B';} } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/favicon.ico"> <title><?=htmlspecialchars($torrent[name])?></title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> <style type="text/css"> body { padding-top: 80px; padding-bottom: 20px; } </style> </head> <body> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/"> RuTracker</a> </div> <div id="navbar" class="navbar-collapse collapse"> <form action="/search.php" method="GET" class="navbar-form navbar-left"> <div class="form-group input-group"> <input type="text" placeholder="" value="" class="form-control" name="q"> <span class="input-group-btn"> <button class="btn btn-primary" type="submit"><i class="glyphicon glyphicon-search"></i></button> </span> </div> </form> </div> <!--/.navbar-collapse --> </div> </nav> <div class="container"> <h1><?=htmlspecialchars($torrent[name])?></h1> <table class="table table-striped"> <tbody> <tr> <th width="20%">:</th> <td><a href="magnet:?xt=urn:btih:<?=$torrent[hash]?>"><i class="glyphicon glyphicon-magnet"></i> Magnet</a></td> </tr> <tr> <th width="20%">:</th> <td><?=bytesToSize($torrent[size])?></td> </tr> <tr> <th width="20%"> :</th> <td><?=$torrent_date?></td> </tr> <tr> <th width="20%">:</th> <td><a target=_blank href="http://rutracker.org/forum/viewforum.php?f=<?=$torrent[cat_id]?>"><?=htmlspecialchars($torrent[cat_name])?></a></td> </tr> <tr> <th width="20%">:</th> <td><a target=_blank href="http://rutracker.org/forum/viewtopic.php?t=<?=$torrent[topic_id]?>"> #<?=$torrent[topic_id]?></a></td> </tr> </tbody> </table> </div> <!-- /.container --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script> </body> </html>







以上です。 RuTrackerのデータベースを使用した完全に機能するWebサイトを取得しました。クイック検索と便利なインターフェイスがあります。 具体的には、カテゴリ、並べ替え、ページネーションなどによる検索フィルタリングを追加しませんでした。そのため、最も必要なコードが最もクリーンになります。 関心がある場合は、コメントまたは別の記事でこれについて全員に伝えます。



ご清聴ありがとうございました。 質問を書いて、みんなに答えます。



All Articles