使用Node爬虫中国所有大学数据(一)

Nest是用于构建高效,可扩展的Node.js服务器端应用程序的框架。它使用渐进式JavaScript,内置并完全支持TypeScript,并结合了OOP(面向对象编程),FP(函数式编程)和FRP(函数响应式编程)。

在底层,Nest默认使用Express这类的健壮的服务端框架,并且你可以选择自己配置使用Fastify

Nest在这些常见的Node.js框架(Express / Fastify)之上提供了一个抽象级别,但也直接向开发者公开了它们的API。 这使开发人员可以自由使用底层平台的第三方库。

这里就不对Nest进行更多介绍了,你可以在Nest官方文档了解更多信息。毕竟本文的重点是展示如何去爬虫。

开始你的Nest应用

 npm i -g @nestjs/cli
 nest new project-name

连接MYSQL数据库

为了与SQL和NoSQL数据库集成,Nest提供了@nestjs/typeorm包。 TypeORM其官方文档称之为是可用于TypeScript的最成熟的对象关系映射器(ORM)。由于它是用TypeScript编写的,因此可以与Nest框架很好地集成。

使用TypeORM和在.Net或者JAVA里使用任何对象关系映射器并没有什么区别,它只是给我们方便的提供诸如find,save,create,remove,update,delete等API,如果你不喜欢,你当然也可以直接使用query传入SQL语句来操作数据库。

npm install --save @nestjs/typeorm typeorm mysql

然后在app.module.ts里:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersModule } from './users/users.module';
import { CollegeModule } from './college/college.module';
import { BachelorPointsModule } from './bachelor-points/backelor.module';
import { MasterPointsModule } from './master-points/master.module';
import { ProvinceModule } from './province-data/province-data.module';
@Module({
 imports: [
   TypeOrmModule.forRoot({
     type:'mysql',
     host:'localhost',
     port:3306,
     username:'root',
     password:'root123456',
     database:'test',
     autoLoadEntities: true,
     synchronize:true
   }),
   UsersModule,CollegeModule,BachelorPointsModule,MasterPointsModule,ProvinceModule
 ],
 controllers: [AppController],
 providers: [AppService],
})
export class AppModule {}

关于这个如果你遇到什么问题,可以参考我的文章Nest.js初探索之实体映射数据库的三种方式

爬取所有省份

为了获取中国所有大学信息,我们希望可以根据省份查询。所以,我们先爬取所有省份。

先创建province实体类
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm';

@Entity()
export class Province {

   @PrimaryGeneratedColumn()
   id: number;

   @Column()
   name: string;

   @Column(
       {
           nullable: true
       }
   )
   abbr: string;

   @CreateDateColumn({ comment: '创建时间',type:'datetime' })  // 自动生成列
   created_ts: string

   @UpdateDateColumn({ comment: '更新时间',type:'datetime'})   // 自动生成并自动更新列
   updated_ts: string


}
然后在controller里面设置Rest API相关信息
import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
import { Province } from './province.entity';
import { ProvinceService } from './province.service';

@Controller('province')
export class ProvinceController {
    constructor(private readonly provinceService: ProvinceService) {
    }
    @Post('crawler')
    crawlerProvince() {
        return this.provinceService.crawlerProvince();
    }

    @Get()
    list(): Promise<Province[]> {
        return this.provinceService.listProvince();
    }


}
在Service里进行爬虫和数据库操作

主要的爬虫逻辑在service里,我们重点看下crawlerProvince方法,使用了Crawler库来解析和爬虫。

import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as Crawler from 'crawler';
import { Province } from './province.entity';

@Injectable()
export class ProvinceService {
    constructor(
        @InjectRepository(Province)
        private provinceRepository: Repository<Province>,
    ) {
    }

    listProvince(): Promise<Province[]> {
        return this.provinceRepository.find();
    }
    async crawlerProvince() {
        const a = () => {
            return new Promise((reslove, reject) => {
                var c = new Crawler({
                    maxConnections: 10,
                    callback: (error, res, done) => {
                        if (error) {
                            console.log(error);
                            reject(error)
                        } else {
                            var $ = res.$;
                            let items = [];
                            $('.row').find('.col-md-12').find('.row').find('.col-md-12').find('a').each(async (idx, element) => {
                                if (idx >= 34) { return; }
                                var $element = $(element);
                                let province = {
                                    name: $element.text(),
                                }
                                await this.provinceRepository.save(province);
                                items.push(province);
                            });
                            reslove(items);

                        }
                        done();
                    }
                });
                c.queue(`http://www.52maps.com/china_city.php`);

            })
        };
        return await a();
    }

}

这里我们使用Crawler爬取页面信息之后,将每个省份使用this.provinceRepository.save(province)都存储进数据库。

module引入

最后我们需要ProvinceModule将controller和service以及实体Province都在module文件里声明,最后在app.module不要忘记导入ProvinceModule。

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Province } from './province.entity';
import { ProvinceController } from './province-data.controller';
import { ProvinceService } from './province.service';
@Module({
  imports: [
    TypeOrmModule.forFeature([Province]),
  ],
  controllers:[ProvinceController],
  providers:[ProvinceService]
})
export class ProvinceModule {}

这时数据库里就有省份信息了:

使用get请求查看我们爬取的结果:

结果

在前端框架我们就可以让用户选择不同的省份来获取相应的大学信息。

下一篇文章,我将介绍如何根据不同的省份爬取大学列表,并爬取百度百科的大学详细信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值