前言
Wget.Fit 于2023.10.24停服了,但是把网站的原理以及源码发出来了,我给搬运过来了,有兴趣的可以自己按照教程尝试搭建一个自己的扒站程序。
00x01
wget首先会对输入的url进行解析并提取出其中的协议路径等信息,
通过该信息wget建立与服务器的连接并发送请求
服务器收到请求报文后会返回相应的响应报文。
wget会将其解析并响应,如请求成功,
服务器会将资源返回至wget,wget根据响应信息,将资源递归保存至本地。
00x02
windows版本下的wget调用
![图片[1]-Wget扒站原理与写一条在线扒站接口[源码]-樱花小镇](https://bu.dusays.com/2023/10/29/653e449490567.png)
@echo off & cd /d %~dp0
mode con cols=100
call :showLogo
pause
exit
:showLogo
title Wget downloads tool 2.0-Wget.fit
color 80
mode con cols=72 lines=22
if not exist .outlogo (
echo IF9fICAgICAgICAgIF9fICAgICAgICBfICAgICBfX19fX18gXyBfICAgX19fICAgIF9fXyAgCiBcIFwgICAgICAgIC8gLyAgICAgICB8IHwgICB8ICBfX19fKF8pIHwgfF9fIFwgIC8gXyBcIAogIFwgXCAgL1wgIC8gL18gXyAgX19ffCB8XyAgfCB8X18gICBffCB8XyAgICkgfHwgfCB8IHwKICAgXCBcLyAgXC8gLyBfYCB8LyBfIFwgX198IHwgIF9ffCB8IHwgX198IC8gLyB8IHwgfCB8CiAgICBcICAvXCAgLyAoX3wgfCAgX18vIHxfIF98IHwgICAgfCB8IHxfIC8gL18gfCB8X3wgfAogICAgIFwvICBcLyBcX18sIHxcX19ffFxfXyhfKV98ICAgIHxffFxfX3xfX19fKF8pX19fLyAKICAgICAgICAgICAgIF9fLyB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgIHxfX18vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA==>.logo
certutil -decode .logo .outlogo>nul
del .logo
)
type .outlogo
echo.
echo The principle of this tool is very simple, is to apply wget with bat
echo Official website: www.wget.fit
echo=====================================================================
set /p a=Url(http/https):
color 2f
mode con cols=80 lines=25
wget.exe -U‘Mozilla/5.0 -r -p -np -k --no-check-certificate %a%
cls
title Wget downloads tool 2.0-Wget.fit
echo The task is complete. Press Enter to exit
echo. &pause >nul
运行如下图
![图片[2]-Wget扒站原理与写一条在线扒站接口[源码]-樱花小镇](https://bu.dusays.com/2023/10/29/653e449874c13.png)
00x02
扒站网站建设
![图片[3]-Wget扒站原理与写一条在线扒站接口[源码]-樱花小镇](https://bu.dusays.com/2023/10/29/653e449870776.png)
这是wget.fit网站的文件目录
│ api.php api接口
│ common.php 网站全局文件
│ Config.php 网站核心文件
│ index.php 网站主页
│ ssh.class.php ssh认证文件
│ wget_site.sh wget请求文件
└─work 网站预览目录
从网站主页说起
网站主页仅用于请求api.php
if (isset($_POST['url'])) {
$url = $_POST['url'];
$email = $_POST['email'];
if (get_code($url) != 200) {
exit(json_encode(array('code' => '-1', 'msg' => '爬取失败,请检查网址是否正确!'),JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
}
$preg = "/^http(s)?:\\/\\/.+/";
if(!preg_match($preg,$url)){
exit(json_encode(array('code' => '-1', 'msg' => '域名请带上协议头!如( http:// 或 https:// )'),JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
}
$file = parse_url($url)['host'].'-'.mt_rand(10000,99999);
$ssh = new Components_Ssh($host, $user, $pass, $port, $log);
$ssh->cmd("bash /www/wwwroot/wget.fit/wget_site.sh {$url} {$file} >/dev/null && echo \"success\"");
if(file_exists('./down/'.$file.'.zip')) {
$content='你在Wget.fit提交的扒站请求已结束,下载链接:wget.fit/down/' . $file . '.zip';
$wz=$smtpapi."?adress=".$email."&isHTML=false&title=Wget.fit爬取成功&content=".$content;
file_get_contents($wz);
exit(json_encode(array('code' => '1', 'msg' => '<center><img src="./assets/simple/img/wget.jpg" width="50%" ></center>', 'down' => 'http://wget.fit/down/' . $file . '.zip', 'yulan' => 'http://wget.fit/work/' . $file . '/' . parse_url($url)['host']),JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
} else {
exit(json_encode(array('code' => '-1', 'msg' => '爬取失败!'),JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
}
} else {
function trans_byte($byte)
{
$KB = 1024;
$MB = 1024 * $KB;
$GB = 1024 * $MB;
$TB = 1024 * $GB;
if ($byte < $KB) {
return $byte . "B";
} elseif ($byte < $MB) {
return round($byte / $KB, 2) . "KB";
} elseif ($byte < $GB) {
return round($byte / $MB, 2) . "MB";
} elseif ($byte < $TB) {
return round($byte / $GB, 2) . "GB";
} else {
return round($byte / $TB, 2) . "TB";
}
}
$list = glob('./down/*.zip');
$count = count($list);
$page_num = isset($_GET['limit'])?$_GET['limit']:10;
$pages = ceil($count / $page_num);
$page = isset($_GET['page'])? $_GET['page']:1;
$startpos = ($page - 1)*$page_num;
$json['code'] = '0';
$json['data'] = $arr;
exit(json_encode($json,JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
}
function get_code($url){
$ch = curl_init();
$timeout = 3;
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch,CURLOPT_URL,$url);
curl_exec($ch);
return $httpcode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
curl_close($ch);
}
主要用于以下功能:
首先,它检查是否有名为 'url' 和 'email' 的POST请求参数被发送。
接着,它使用 get_code 函数来检查指定URL的HTTP响应代码是否为200。如果不是200,它将返回一个JSON响应,指示爬取失败并提供错误消息。
接下来,它检查URL是否以"http://"或"https://"开头,如果不是,它会返回一个JSON响应,指示URL应该包含协议头。
然后,它生成一个随机文件名($file),该文件名包括URL的主机名和一个随机数。
通过SSH连接到服务器,并运行一个bash命令来执行爬取操作,将结果保存到名为$file.zip的文件中。
如果爬取成功并且文件存在,它将构建一个包含下载链接的消息,并通过SMTP发送到指定的电子邮件地址。
最后,它返回一个JSON响应,其中包含成功或失败的代码,以及相应的消息和链接。
如果没有接收到 'url' 参数,它将跳转到下面的代码段。
下面的代码段包含了两个函数和一些变量:
trans_byte 函数用于将字节数转换为更容易阅读的格式,如KB,MB,GB,TB等。
$list 变量通过 glob 函数获取指定目录下的所有ZIP文件的文件名,并存储在一个数组中。
$count 变量用于存储ZIP文件的数量。
$page_num 从GET请求参数中获取,用于指定每页显示的ZIP文件数量。
$pages 计算总页数,以便进行分页显示。
$page 从GET请求参数中获取,指示当前页数。
$startpos 用于计算分页的起始位置。
get_code 函数用于检查指定URL的HTTP响应代码。它使用CURL来执行HTTP请求,获取响应代码,并返回它。
以下是对这段代码的注释:
if (isset($_POST['url'])) {
// 检查是否有POST请求参数 'url'
$url = $_POST['url'];
$email = $_POST['email'];
// 获取POST请求中的URL和电子邮件地址
if (get_code($url) != 200) {
// 使用 get_code 函数检查指定URL的HTTP响应代码是否不等于200
exit(json_encode(array('code' => '-1', 'msg' => '爬取失败,请检查网址是否正确!'),JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
// 如果响应代码不等于200,返回一个JSON响应,指示爬取失败
}
$preg = "/^http(s)?:\\/\\/.+/";
if(!preg_match($preg, $url)){
// 使用正则表达式检查URL是否以"http://"或"https://"开头
exit(json_encode(array('code' => '-1', 'msg' => '域名请带上协议头!如( http:// 或 https:// )'),JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
// 如果URL没有协议头,返回一个JSON响应,提醒用户添加协议头
}
$file = parse_url($url)['host'].'-'.mt_rand(10000,99999);
// 生成一个随机文件名,包括URL的主机名和一个随机数
$ssh = new Components_Ssh($host, $user, $pass, $port, $log);
// 创建SSH连接对象
$ssh->cmd("bash /www/wwwroot/wget.fit/wget_site.sh {$url} {$file} >/dev/null && echo \"success\"");
// 在服务器上执行bash命令,执行爬取操作
if(file_exists('./down/'.$file.'.zip')) {
// 如果爬取成功并且文件存在
$content='你在Wget.fit提交的扒站请求已结束,下载链接:wget.fit/down/' . $file . '.zip';
$wz=$smtpapi."?adress=".$email."&isHTML=false&title=Wget.fit爬取成功&content=".$content;
file_get_contents($wz);
// 发送包含下载链接的消息到指定的电子邮件地址
exit(json_encode(array('code' => '1', 'msg' => '<center><img src="./assets/simple/img/wget.jpg" width="50%" ></center>', 'down' => 'http://wget.fit/down/' . $file . '.zip', 'yulan' => 'http://wget.fit/work/' . $file . '/' . parse_url($url)['host']),JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
// 返回一个JSON响应,指示爬取成功,并包含相关信息和链接
} else {
exit(json_encode(array('code' => '-1', 'msg' => '爬取失败!'),JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
// 如果爬取失败,返回一个JSON响应
}
} else {
// 如果没有接收到 'url' 参数
function trans_byte($byte)
{
// 定义一个函数,用于将字节数转换为更易读的格式
$KB = 1024;
$MB = 1024 * $KB;
$GB = 1024 * $MB;
$TB = 1024 * $GB;
if ($byte < $KB) {
return $byte . "B";
} elseif ($byte < $MB) {
return round($byte / $KB, 2) . "KB";
} elseif ($byte < $GB) {
return round($byte / $MB, 2) . "MB";
} elseif ($byte < $TB) {
return round($byte / $GB, 2) . "GB";
} else {
return round($byte / $TB, 2) . "TB";
}
}
$list = glob('./down/*.zip');
$count = count($list);
// 获取指定目录下的ZIP文件列表和文件数量
$page_num = isset($_GET['limit'])?$_GET['limit']:10;
// 获取每页显示的ZIP文件数量,如果未指定则默认为10
$pages = ceil($count / $page_num);
// 计算总页数
$page = isset($_GET['page'])? $_GET['page']:1;
// 获取当前页数,如果未指定则默认为第一页
$startpos = ($page - 1)*$page_num;
// 计算分页的起始位置
$json['code'] = '0';
$json['data'] = $arr;
// 构建JSON响应
exit(json_encode($json,JSON_UNESCAPED_UNICODE| JSON_PRETTY_PRINT));
}
function get_code($url){
$ch = curl_init();
$timeout = 3;
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch,CURLOPT_URL,$url);
curl_exec($ch);
return $httpcode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
curl_close($ch);
}
进入下一个文件:ssh_class.php
这是一个PHP类 Components_Ssh,它用于建立SSH连接和执行远程命令。以下是对这个类的代码注释:
<?php
class Components_Ssh {
private $host; // SSH服务器主机名
private $user; // SSH登录用户名
private $pass; // SSH登录密码
private $port; // SSH服务器端口
private $conn = false; // SSH连接状态
private $error; // SSH连接错误信息
private $stream; // SSH执行命令的流
private $stream_timeout = 100; // SSH执行命令的超时时间
private $log; // 日志信息
private $lastLog; // 最后一条日志
private $sLog; // 服务器日志记录标志
public function __construct ( $host, $user, $pass, $port, $serverLog ) {
// 构造函数,接收SSH连接所需的参数
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$this->port = $port;
$this->sLog = $serverLog;
if ( $this->connect ()->authenticate () ) {
return true;
}
}
public function isConnected () {
// 检查SSH连接状态
return ( boolean ) $this->conn;
}
public function __get ( $name ) {
// 获取类的属性
return $this->$name;
}
public function connect () {
// 建立SSH连接
$this->logAction ( "正在链接 -> {$this->host}" );
if ( $this->conn = ssh2_connect ( $this->host, $this->port ) ) {
return $this;
}
$this->logAction ( "链接失败 -> {$this->host}" );
//exit ( "Unable to connect to {$this->host}" );
}
public function authenticate () {
// SSH认证
$this->logAction ( "正在认证 -> {$this->host}" );
if ( ssh2_auth_password ( $this->conn, $this->user, $this->pass ) ) {
return $this;
}
$this->logAction ( "认证失败 -> {$this->host} failed" );
//exit ( "Unable to authenticate to {$this->host}" );
}
public function cmd ( $cmd, $returnOutput = false ) {
// 执行SSH命令
$this->logAction ( "执行命令 -> $cmd" );
$this->stream = ssh2_exec ( $this->conn, $cmd );
if ( FALSE === $this->stream ) {
$this->logAction ( "执行失败 -> $cmd" );
//exit ( "Unable to execute command '$cmd'" );
}
$this->logAction ( "执行成功 -> $cmd" );
stream_set_blocking ( $this->stream, true );
stream_set_timeout ( $this->stream, $this->stream_timeout );
$this->lastLog = stream_get_contents ( $this->stream );
$this->logAction ( "命令输出 -> [$cmd]:{$this->lastLog}" );
fclose ( $this->stream );
$this->log .= $this->lastLog . "\n";
return ( $returnOutput ) ? $this->lastLog : $this;
}
public function shellCmd ( $cmds = array () ) {
// 在虚拟终端中执行SSH命令
$this->logAction ( "虚拟终端 -> 终端已打开" );
$this->shellStream = ssh2_shell ( $this->conn );
sleep ( 1 );
$out = '';
while ( $line = fgets ( $this->shellStream ) ) {
$out .= $line;
}
$this->logAction ( "虚拟终端 -> [输出]:$out" );
foreach ( $cmds as $cmd ) {
$out = '';
$this->logAction ( "执行命令 -> $cmd" );
fwrite ( $this->shellStream, "$cmd" . PHP_EOL );
sleep ( 1 );
while ( $line = fgets ( $this->shellStream ) ) {
$out .= $line;
sleep ( 1 );
}
$this->logAction ( "命令输出 -> [$cmd]:$out" );
}
$this->logAction ( "虚拟终端 -> 终端已关闭" );
fclose ( $this->shellStream );
}
public function getLastOutput () {
// 获取最后一次SSH命令的输出
return $this->lastLog;
}
public function getOutput () {
// 获取所有SSH命令的输出
return $this->log;
}
public function disconnect () {
// 断开SSH连接
$this->logAction ( "正在断开 -> {$this->host}" );
// 如果有断开函数,调用它
if ( function_exists ( 'ssh2_disconnect' ) ) {
ssh2_disconnect ( $this->conn );
}
else { // 如果没有断开函数,关闭连接并取消变量
@fclose ( $this->conn );
$this->conn = false;
}
// 总是返回NULL
return NULL;
}
public function logAction ( $message ) {
// 记录日志
if ( $this->sLog == 'true' ) {
$this->lastLog = $this->log;
$this->log = $message;
//echo $message .'<br>';
}
}
}
这个类主要用于SSH连接和执行命令,还有日志记录功能。
wget_site.sh
#!/bin/sh
wget -r -p -np -k -P /www/wwwroot/wget.fit/work/$2 $1
cp /www/wwwroot/wget.fit/readme.txt /www/wwwroot/wget.fit/work/$2/readme.txt
cd /www/wwwroot/wget.fit/work/$2/
zip -r $2.zip ./
mv $2.zip /www/wwwroot/wget.fit/down
rm -rf /www/wwwroot/wget.fit/work/$2
以下是对这段Shell脚本代码的注释:
bash
#!/bin/sh
# 上一行指定了脚本使用的Shell,这里是Bash。
# 使用wget命令下载指定URL的内容,并进行以下操作:
wget -r -p -np -k -P /www/wwwroot/wget.fit/work/$2 $1
# -r: 递归下载整个目录
# -p: 下载所有页面相关资源
# -np: 不遍历父目录
# -k: 将HTML文件中的链接转换为本地链接
# -P /www/wwwroot/wget.fit/work/$2: 指定下载文件的存储路径,$2 是第二个参数,通常是一个文件夹名。
# 复制readme.txt文件到下载目录下
cp /www/wwwroot/wget.fit/readme.txt /www/wwwroot/wget.fit/work/$2/readme.txt
# 进入下载目录
cd /www/wwwroot/wget.fit/work/$2/
# 压缩下载的文件和目录为一个ZIP文件
zip -r $2.zip ./
# $2 是第二个参数,通常是一个文件夹名,这将创建一个以文件夹名命名的ZIP文件。
# 移动ZIP文件到下载目录
mv $2.zip /www/wwwroot/wget.fit/down
# 删除下载工作目录及其内容
.rm -rf /www/wwwroot/wget.fit/work/$2
用于递归删除目录及其内容。
总结:这个脚本首先使用wget命令下载指定URL的内容到指定目录,然后将readme.txt文件复制到下载目录,接着将下载目录中的内容压缩为ZIP文件,最后将ZIP文件移动到另一个目录,.rm -rf /www/wwwroot/wget.fit/work/$2是故意写错的,为了留下文件预览。
至此一个属于自己的扒站平台搭建成功。
原文链接:https://www.1042.net/5.html

暂无评论内容