使用 QueryList + Redis 下载壁纸

2018-09-08
3分钟阅读时长

完整代码:https://github.com/her-cat/wallpaper_crawler

页面分析

  • 壁纸站地址:http://www.huanse.net/

打开网站首页,通过审查元素找到详情页面和略缩图的地址(下图红框部分)。

  • 详情页面地址: ./wallpaper-6873.html
  • 略缩图地址:./uploads/thumb/thumb-6873.jpg

可以看到这两个地址中都有 6873 这个数字,先猜测一下这个数字是这张壁纸的id,也就是唯一标识符。

为了验证猜测是否正确,打开详情页面对 点击按钮下载 右键审查元素,就看到下载壁纸的url。

这里写图片描述
这里写图片描述

从下载地址中可以看到 wallpaper=6873 这个参数,现在就能确认 6873 是壁纸的id。

window.open('./download.php?wallpaper=6873&type=1')

也就是说只要知道壁纸的id,就可以得到壁纸的下载地址。

http://www.huanse.net/download.php?wallpaper={壁纸id}&type=1

所以爬取的流程就是获取壁纸id,拼接出下载地址,然后下载壁纸。

爬取壁纸id

壁纸的id在列表页就已经有了,所以我们只需要对列表页进行循环爬取就行了。

这里写图片描述
这里写图片描述

使用到的工具:

  • QueryList QueryList具有jQuery一样的DOM操作能力,这样就不用写正则表达式了
  • predis php连接redis的操作库,用来保存壁纸id

require 'vendor/autoload.php';
use QL\QueryList;
use Predis\Client;


// 实例化 redis 连接
$client = new Predis\Client('tcp://127.0.0.1:6379');

$page = 1;
do {
    // 使用 QueryList 获取 html 网页内容,找到所有 img 标签的 data-echo 属性的值
    $data = QueryList::get("http://www.huanse.net/new-{$page}.html")->find('img')->attrs('data-echo');
    if (count($data) > 0) {
        foreach ($data as $datum) {
            if ($datum) {
                // 通过分割字符串得到壁纸id
                $wallpaper_id = explode('.', explode('-', $datum)[1])[0];
                // 将壁纸id push 到 redis 中
                $client->lpush('wallpaper_id_queue', $wallpaper_id);
            }
        }
    } else {
        echo 'no data. page: ' . $page . PHP_EOL;
        break;
    }
    $page++;
    echo 'now page: ' . $page . PHP_EOL;
}while(true);


运行截图:

这里写图片描述
这里写图片描述

Redis 中保存的壁纸id

这里写图片描述
这里写图片描述

下载壁纸

下载壁纸这一步很简单,只需要从 redis 中不停的取出壁纸id,然后通过下载地址将壁纸下载到本地。

require 'vendor/autoload.php';

use QL\QueryList;
use Predis\Client;


$client = new Predis\Client('tcp://127.0.0.1:6379');

while(true) {
    // 从 redis 中取出壁纸id
    $wallpaper_id = $client->rpop('wallpaper_id_queue');
    if($wallpaper_id == 'nil' || $wallpaper_id == ''){
        // 如果壁纸id为空的话就休眠5秒钟
        echo 'not have wallpaper data, sleep 5 second...' . PHP_EOL;
        sleep(5);
        continue;
    }

    try {
        downloadWallpaper($wallpaper_id);
        // 验证壁纸是否保存成功
        if (file_exists('./wallpaper/' . 'wallpaper-' . $wallpaper_id . '.jpg')) {
            echo 'success: ' . $wallpaper_id . PHP_EOL;
        } else {
            echo 'fail: ' . $wallpaper_id . PHP_EOL;
        }
    } catch (Exception $e) {
        echo 'img exception, sleep 1 second...' . PHP_EOL;
        sleep(1);
    }
};


/**
 * 下载壁纸
 * @param $wallpaper_id
 * @return int
 */
function downloadWallpaper($wallpaper_id) {
    // 拼接下载地址
    $download_url = $url = "http://www.huanse.net/download.php?wallpaper={$wallpaper_id}&type=1";
    set_time_limit (24 * 60 * 60);
    $destination_folder = './wallpaper/';
    if (!is_dir($destination_folder)) {
        mkdirs($destination_folder);
    }
    $newfname = $destination_folder . 'wallpaper-' . $wallpaper_id . '.jpg';
    $file = fopen ($url, "rb");
    if ($file) {
        $newf = fopen ($newfname, "wb");
        if ($newf)
            while (!feof($file)) {
                fwrite($newf, fread($file, 1024 * 8), 1024 * 8);
            }
    }
    if ($file) {
        fclose($file);
    }
    if ($newf) {
        fclose($newf);
    }
    return 0;
}

##运行效果 运行截图:

这里写图片描述
这里写图片描述

保存的壁纸:

这里写图片描述
这里写图片描述

爬取壁纸id脚本的脚本用一个窗口执行就够了,下载壁纸的脚本可以多开几个窗口运行,提高壁纸下载速度。

本文作者:她和她的猫
本文地址https://her-cat.com/posts/2018/09/08/use-querylist-redis-to-download-wallpaper/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!