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

页面分析

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

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

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

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

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

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

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

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

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

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

爬取壁纸id

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

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

使用到的工具:

  • QueryList QueryList具有jQuery一样的DOM操作能力,这样就不用写正则表达式了
  • predis php连接redis的操作库,用来保存壁纸id
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

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,然后通过下载地址将壁纸下载到本地。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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脚本的脚本用一个窗口执行就够了,下载壁纸的脚本可以多开几个窗口运行,提高壁纸下载速度。