一. 在浏览器上运行爬虫

第一步:获取文件下载链接与文件名,整理为数组(借助油猴脚本这个工具)

let curIdx = parseInt(window.location.pathname.match(/\d+/g)[1])
let nxtUrl = window.location.href.replace(/index\d+/, `index${curIdx + 1}`)

let files = []
$('div.threadinfo').each(function() {
    let src = $(this).find('.preview').attr('src')
    let filename = textProcess($(this).find('h3.threadtitle >a').text())
    files.push({src, filename})
})

exportInfo()

function textProcess(text) {
    text = text.replace(/\[.+?\]/g, '')
    text = text.replace('~NEW~', '')
    text = text.replace('~Vintage~', '')
    text = text.replace('_', '')
    text = text.trim()
    text = text.replace('[', '')
    text = text.replace(']', '')
    text = text + '.jpg'
    return text
}

function exportInfo() {
    var data = `data:text/plain;charset=utf-8,${JSON.stringify(files)}`
    var filename = `animeshare${curIdx}.txt`
    download(data, filename)
}

function download(url, filename) {
    let a = document.createElement('a')
    a.href = url
    a.download = filename
    a.click()
}

第二步: 用命令行合并文本文件,修改后得到一个大文件对象数组

cat *.txt > all.txt
# 然后记事本替换 ][ 为 ,

第三步: 打开浏览器,在开发者工具的 snippets 输入以下代码,替换 imgArr 值为大文件内容,执行

let imgArr = []         // 文件对象数组(提供下载信息)
let queueSize = 200     // 每次同时下载文件数目
let frequency = 60000   // 文件下载时间间隔
let timer = 0           // 间隔下载计时器

start()

function start() {
    imgArr.splice(0, queueSize).forEach(img => download(img.src, img.filename))
    timer = setInterval(() => {
        let imgFragment = imgArr.splice(0, queueSize)
        imgFragment.forEach(img => download(img.src, img.filename))
        
        if(imgArr.length <= 0) {
            clearInterval(timer)
            console.log('mission complete!')
        } else {
            console.log('left files:', imgArr.length)
        }
    }, frequency)
}

function pause() {
    clearInterval(timer)
}

function download(url, filename) {
    let a = document.createElement('a')
    a.href = url
    a.download = filename
    a.click()
}

知识点总结

  • 从浏览器导出文本文件并保存 (function exportInfo)
  • 合并多个文本文档的命令行
  • 浏览器一次性下载多个文件会立刻崩溃,利用 setInterval 分批下载解决崩溃问题

二. 探索过程

  • 最开始用油猴脚本爬取页面所有图片的地址与文件名,一一下载

    • 分页较少的情况下表现良好,但是他总共 3000 多页导致我不得不认为这是个糟糕的方案,而且每爬取 100 页左右就有可能 ip 失效网页无法访问
  • 然后想用 node.js

    • 遇到了文件名保存出错的坑,而且就算不出错也可能像以往那样半途卡住
  • 接着想到先爬取所有图片的地址与文件名保存到文本文件,再根据文本批量下载

    • 爬取文件很顺利,之前写的脚本改进一下,逐页导出 + 自动跳转很快到手所有链接地址
    • 下载的时候先用迅雷试一下,发现速度不够快
    • 然后改用浏览器下载,速度明显改善(即:浏览器也可以当爬虫
    • 缺点是仍然有部分文件下载失败,因为不打算重新下载所以 ok

三.powershell 与文件处理

由于这部分我是边查边实现的,所以用问题 + 方案的形式整理

如何每 50 个 50 个文件放到一个文件夹?

利用 powershell 完成

Dir *.jpg | select -first 50 | ForEach-Object {Move-Item ($_.FullName) .\animeshare66\}

其中,

  • Dir *.jpg 是查询对象
  • | select -first 50 查询前 50 个文件。
  • For-Each-Object {} 是针对查询结果的批量操作,内部的 $_ 指单个查询结果本身(类似数组 api 第一个参数)
powershell 中,如何把文件查询结果排序?
Dir *.jpg | Sort-Object LastWriteTime | select -first 50 | ForEach-Object {Move-Item ($_.FullName) .\animeshare77\}
powershell 如何自定义函数?
Function moveFile {
    Param
    (
    $num
    )
    $folder = "animeshare" + $num
    new-item $folder -type directory
    Dir *.jpg | Sort-Object LastWriteTime | select -first 50 | ForEach-Object {Move-Item ($_.FullName) .\$folder\}
}

调用是

moveFile 1
  • 函数定义结构: Function xx {},大括号内部先写参数部分 Param ($a; $b) 再换行接写函数体
  • 调用时参数没有括号,空格隔开
powershell 如何写一个循环?
for($i=1;$i -le 100;$i++)
{
    moveFile $i
}
powershell 如何自定义变量,如何拼接字符串?
$num = 1
$folder = "animeshare" + $num