成功实现了捷程评论的爬虫,现在需要把这个爬虫放到后端nestjs项目中,把它作为一个接口来调用。
首先,在nestjs项目的根目录下创建一个python(随便叫什么名字)文件夹,将python文件放在这个文件夹中。 结构层次如下:
js
- nest-app
- src
- user
- user.service.ts
- python
- spider.py
接下来,要实现在service中调用python,在user.service.ts 首先,通过 require('child_process')
引入 child_process
模块,这个模块用于在项目中执行外部进程。
接着,创建一个 Promise 对象,该 Promise 用于封装 Python 脚本的执行过程,以便进行异步操作。
return new Promise((resolve, reject) => {
使用 spawn
方法创建了一个子进程 pythonProcess
,并指定要执行的命令是 python
,以及传递给脚本的参数,其中 ../python/spider.py
是 Python 脚本的路径,keyword
是传递给脚本的参数。
const pythonProcess = spawn('python', ['../python/spider.py', keyword]);
这里要注意的是,因为需要给python传递参数,python脚本中要加上下面这段代码来传递参数
python
import sys
# 获取关键字参数
keyword = sys.argv[1]
pythonProcess.stdout.on('data', ...)
处理子进程的标准输出。每当子进程输出数据时,将数据追加到 result
变量中,这个变量最终将包含 Python 脚本的标准输出内容。
pythonProcess.stderr.on('data', ...)
处理子进程的错误输出。同样,每当子进程输出错误信息时,将其追加到 errorOutput
变量中。
pythonProcess.on('close', ...)
处理子进程的关闭事件。当子进程执行完成后,会触发这个事件。如果进程的退出码是 0,表示执行成功,会调用 resolve
方法并返回 result
变量中的内容,否则,表示执行出错,会调用 reject
方法返回错误信息,其中包括退出码和错误输出信息。
相应的python脚本中也将对应的输出通过print
返回
python代码见根据景区关键词爬取捷程的景区评论的方法 - 掘金 (juejin.cn)
下面是service.ts里的完整代码
js
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm';
import { UserEntity } from './entities/user.entity';
@Injectable()
export class UserService {
// 使用InjectRepository装饰器并引入Repository这样就可以使用typeorm的操作了
constructor(
@InjectRepository(UserEntity)
private readonly userRepository: Repository<UserEntity>,
) { }
async runPythonScraper(keyword: string) {
const { spawn } = require('child_process');
return new Promise((resolve, reject) => {
const pythonProcess = spawn('python', ['../python/spider.py', keyword]);
let result = '';
let errorOutput = ''; // 用于存储错误输出信息
pythonProcess.stdout.on('data', (data) => {
result += data.toString();
});
pythonProcess.stderr.on('data', (data) => {
errorOutput += data.toString();
});
pythonProcess.on('close', (code) => {
if (code === 0) {
console.log('Python脚本成功执行');
resolve(result); // 成功执行时返回结果
} else {
console.error(`Python脚本执行出错,退出码:${code}`);
console.error(`Python脚本错误输出:${errorOutput}`);
reject(`Python脚本执行出错,退出码:${code}, 错误输出:${errorOutput}`); // 执行出错时返回错误信息
}
});
});
}
}
最后,为它写一个POST
js
@Post('comments')
async scrapeData(@Body() requestBody: { keyword: string }) {
const keyword = requestBody.keyword;
// 在此处调用Python脚本并传递关键字
const result = await this.userService.runPythonScraper(keyword);
console.log(result);
// 将结果发送给前端
return result;
}
完工!
接口如下(目前是可以使用的):