这两天hxd找我写一道面试题,要求使用typescript
typescript是JavaScript的一个超集,它具有类型系统并且可以编译成普通的JavaScript代码。

1. 从多个网页爬取内容,然后进行解析

有10个网页,1.txt 到 10.txt

http://dy-public.oss-cn-shenzhen.aliyuncs.com/interviewTestData/1.txt

1
2
<abc> <de
f>data : 1992; name : agent 1 </def></abc>
  1. 格式有可能有区别
  2. 用 promise, async, await 分别实现并发、串行爬取
  3. 网页下载使用nodejs的http即可
  4. 使用正则表达式获取data后面的字段,将10个文件的data值全部获取,并相加

网络请求

Node.js 有大量的网络请求模块,题目这里要求用node的http模块
http模块是node自带的,使用起来十分简单,代码如下:

1
2
3
4
5
6
7
8
http.get(url, res => {
res.setEncoding('utf8')
res.on('data', data => {
resolve(data)
})
}).on('error', (e) => {
reject(e.message)
})

http模块还可以指定options,但这里只需要下载网页,因此使用简单的get请求足以。

爬虫主体

爬虫大致分为两部分-> 网络请求数据清理, 网络请求已经实现了,剩下就是把请求回来的数据进行清理了。这里也没啥多的选择,题目要求使用正则表达式,简单的构建整理一下就得到了下面的代码:

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
import * as http from 'http'

class Spider {
sum: Number
constructor() {
this.sum = 0
}
httpGet(url) {
return new Promise((resolve, reject) => {
http.get(url, res => {
res.setEncoding('utf8')
res.on('data', data => {
resolve(data)
})
}).on('error', (e) => {
reject(e.message)
})
})
}
render(urls) {
urls.reduce((promise, url) => {
return promise.then(_ => {
return this.httpGet(url)
}).then(node => {
return this.flush(node)
}).then(res => {
this.sum += res
})
.catch(e => console.log(e))
}, Promise.resolve())
}
flush(data) {
return new Promise(resolve => {
const re = /:\s(\d+?);/gi
const number = Number(re.exec(String(data))[1])
resolve(number)
})
}
}

let baseUrl = 'http://dy-public.oss-cn-shenzhen.aliyuncs.com/interviewTestData/'
let urlList = []
for (let index = 1; index <= 10; index++) {
urlList.push(`${baseUrl}${index}.txt`)
}

const spider = new Spider()
spider.render(urlList)
// 模拟等待微队列运行完成, 可以用await语法糖
// 这里只是写个大题的框架罢了,后面根据具体的要求改动
setTimeout(() => {
console.log(spider.sum)
}, 5000);

The End

到此为止,整个爬虫就写完了,总结一下体验。typescript是具有类型系统,这对于我这写多了python和JavaScript的人来说太好上手了!