1. NestJS 进行爬虫
Nest.js 是一个基于 Node.js 和 TypeScript 的后端框架,它内置了许多实用的功能和工具,如模块化架构、依赖注入、路由处理、中间件、拦截器和管道等。
在 Nest.js 中进行爬虫开发时,可以使用第三方库 cheerio
或 puppeteer
来实现网页信息的获取和解析。
此处我们使用cherrio。
- cheerio: Cheerio 是一个类似于 jQuery 的库,主要用于在 Node.js 中解析、操作和遍历 HTML 和 XML 文档。
- axios 网络请求库可以发送http请求
2. 爬取图片
https://www.测试.com/Cosplay/Cosplay10772.html
spider.controller.ts
import { Controller, Get } from '@nestjs/common';
import { SpiderService } from './spider.service';
import axios from 'axios';
import * as cheerio from 'cheerio';
@Controller('spider')
export class SpiderController {
constructor(private readonly spiderService: SpiderService) {}
@Get()
findAll() {
const baseUrl = 'https://www.111.com';
axios
.get('https://www.111.com/Cosplay/Cosplay10772.html')
.then((res) => {
// console.log(res.data);
const $ = cheerio.load(res.data);
const urls: string[] = [];
const imgs = $('.article-content p img').each(function (index, item) {
// console.log(index, item);
urls.push(baseUrl + $(this).attr('src'));
});
console.log(urls);
});
return this.spiderService.findAll();
}
}
获取的结果
完整版:
最后一页没有下一页,可以通过判断有没有该值,决定请求是否结束。结束拿到所有结果,将其写入服务器。
path fs 需要通过 * as 进行引入
import { Controller, Get } from '@nestjs/common';
import { SpiderService } from './spider.service';
import axios from 'axios';
import * as cheerio from 'cheerio';
import * as path from 'path';
import * as fs from 'fs';
@Controller('spider')
export class SpiderController {
constructor(private readonly spiderService: SpiderService) {}
@Get()
async findAll() {
const baseUrl = 'https://www.111.com';
const next = '下一页';
let index = 0;
const urls: string[] = [];
const getCosplayImage = async () => {
const res = await axios.get(
`https://www.111.com/Cosplay/Cosplay10772${
index !== 0 ? `_${index}` : ''
}.html`,
);
const $ = cheerio.load(res.data);
// 找出分页的所有dom元素
const pages = $('.article-content .pagination a')
.map(function () {
return $(this).text();
})
.toArray();
if (pages.includes(next)) {
$('.article-content p img').each(function () {
console.log($(this).attr('src'));
urls.push(baseUrl + $(this).attr('src'));
});
index++;
await getCosplayImage();
}
};
await getCosplayImage();
this.saveImages(urls);
return this.spiderService.findAll();
}
// 保存到服务器
saveImages(urls: string[]) {
urls.forEach(async (url) => {
const buffer = await axios
.get(url, { responseType: 'arraybuffer' })
.then((res) => res.data);
const ws = fs.createWriteStream(
path.join(__dirname, '../images/' + new Date().getTime() + '.jpg'),
);
ws.write(buffer);
});
}