惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Spread Privacy
Spread Privacy
K
Kaspersky official blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Forbes - Security
Forbes - Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
The Last Watchdog
The Last Watchdog
SecWiki News
SecWiki News
Attack and Defense Labs
Attack and Defense Labs
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
S
Secure Thoughts
WordPress大学
WordPress大学
Microsoft Security Blog
Microsoft Security Blog
P
Proofpoint News Feed
云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
Security Latest
Security Latest
TaoSecurity Blog
TaoSecurity Blog
Cyberwarzone
Cyberwarzone
S
SegmentFault 最新的问题
Cloudbric
Cloudbric
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
T
The Blog of Author Tim Ferriss
H
Hacker News: Front Page
C
Cybersecurity and Infrastructure Security Agency CISA
小众软件
小众软件
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
AWS News Blog
AWS News Blog
AI
AI
G
GRAHAM CLULEY
IT之家
IT之家
P
Privacy & Cybersecurity Law Blog
L
Lohrmann on Cybersecurity
Last Week in AI
Last Week in AI
D
Docker
Recent Announcements
Recent Announcements
O
OpenAI News
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
S
Security @ Cisco Blogs
T
Troy Hunt's Blog
C
Check Point Blog
博客园 - 三生石上(FineUI控件)
A
About on SuperTechFans
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
N
News and Events Feed by Topic

文章列表 - 她和她的猫

使用小鹤双拼一个月 折腾 Hugo PaperMod 主题 去长鹿旅游休博园 1Password 自动化登录堡垒机 深入 Hyperf:Inject 注解是如何工作的? 译|理解容器镜像层 使用 Rust 实现高性能预写日志(Write Ahead Log) 译|使用 Linux 命名空间隔离系统 深入 Hyperf:HTTP 服务是如何处理请求的? Linux 文件权限学习笔记 译|了解 Bitcask:基于日志结构的 KV 存储引擎 还原 SM2 压缩公钥的几种方法 深入 Hyperf:HTTP 服务启动时发生了什么? 一次 Hyperf 注解失效问题分析 将博客迁移到又拍云 译|PHP 7 新的 Hashtable 实现 排查 ES 查询问题:深入了解 json_encode() 函数 浅析 Redlock 分布式锁实现原理 Yar 源码阅读笔记:RPC 服务端 Yar 源码阅读笔记:客户端的并行调用 Yar 源码阅读笔记:客户端的同步调用 Yar 源码阅读笔记:数据传输模块 Yar 源码阅读笔记:消息编码模块 Yar 源码阅读笔记:RPC 通信协议 Yar 源码阅读笔记:开篇 PHP 8 新特性介绍 基于 OpenSSL 实现国密 SM4 加解密 PHP 源码阅读笔记:编译与调试 PHP 什么是惊群问题 大端模式和小端模式 基于 GitHub Actions 定时推送网址到百度站长平台 聊聊五种 I/O 模型 Workerman 源码分析:文件上传 浅入浅出 HTTP 协议 PHP 网络编程:构建 MySQL 蜜罐获取攻击者微信 ID 使用 Workerman 接入 Bilibili 直播弹幕协议 使用 GitHub Actions 自动部署 Hexo 什么是二进制安全 【转载】PHP 程序员进阶之路 优化 Workerman 检查主进程是否存活的逻辑 基于 Redis 实现分布式锁 《PHP 实现 Base64 编码/解码》笔记 PHP 多进程下载必应壁纸 基于 Redis 实现延迟队列 【转载】PHP 实现 Base64 编码/解码 使用 MySQL FIELD() 函数自定义排序规则 Laravel 的 Facades 实现原理 C语言单链表实现约瑟夫环 数据结构学习笔记:顺序栈和链栈(C语言) 在 Laravel 登录/注册中使用 mews/captcha 扩展包 使用 mews/captcha 扩展包为 Laravel 应用添加图片验证码 给 YOURLS 短网址系统编写插件《批量生成短网址》 给 YOURLS 短网址系统编写插件《Hello World!》 PHP 7.1 使用 json_encode 函数造成浮点类型数据出现精度问题 Laravel 授权策略(Policy)的基本使用 Ubuntu 系统下 WiFi 频繁掉线解决方法 Laravel 应用部署到 Nginx 服务器上的第一个坑 Ubuntu 16.04 LST 安装 Redis 和 Composer PHP 采集逐浪小说章节列表 Nginx 环境 SSL 强制 HTTP 301 跳转到 HTTPS 【工作&生活】第一周 ServiceStack.Redis 与多线程 Count the number of Duplicates C# Base64 加密及解密 ASP.NET MVC 使用动态类型传递数据 Django 使用 order_by() 对数据进行排序操作 ASP.NET + jQuery + AJAX 实现用户登录 ASP.NET 从客户端中检测到有潜在危险的 Request.Form 值 ASP.NET 使用 FormData 实现 AJAX 上传图片 Python 使用 BeautifulSoup 抓取网页 贪心算法之字符串的完美度 一言不和就造轮子之 CookieHelper ASP.NET 上传图片 DBHelper 类 C# 捕获屏幕源码 用 JavaScript 做一些有趣的事情 第一篇文章 好久不见。 如何防止非法调用 PHP 文件 清明小记。 PHP 生成随机字符串 Z-Blog PHP 程序做 301 跳转 PHP 处理数组常用的几个函数 Sublime Text 3 快捷键总结 PHP 使用 file_get_contents() 函数实现采集网页 使用 C# 编写学生信息管理系统 终于到了。 zblog报错: magic_quotes_gpc 和 safe_mode 世事无常。 如何使用 PHP 上传文件 安卓手机编写和运行 PHP 程序的软件 使用 AJAX 刷新、验证 PHP 图片验证码 PHP 生成图片验证码 PHP 之 session 的使用方法 PHP 之 cookie 的使用方法 PHP 实现分页原理详解 Thinkphp 框架中系统常量在 Js 文件中不解析的解决方法
使用 QueryList + Redis 下载壁纸
她和她的猫 · 2018-09-08 · via 文章列表 - 她和她的猫

完整代码: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脚本的脚本用一个窗口执行就够了,下载壁纸的脚本可以多开几个窗口运行,提高壁纸下载速度。