const log = console.log // 缩写 console.log
const TOTAL_PAGE = 50 // 定义需要爬取的网页数量,对应页面下部的跳转链接
// 定义要爬去的数据结构
interface IWriteData {
link: string // 爬取到的商品详情链接
picture: string // 爬取到的图片链接
price: number // 价格,number类型,需要从爬取下来的数据进行转型
title: string // 爬取到的商品标题
}
// 格式化的进度输出 用来显示当前爬取的进度
function formatProgress (current: number): string {
let percent = (current / TOTAL_PAGE) * 100
let done = ~~(current / TOTAL_PAGE * 40)
let left = 40 - done
let str = `当前进度:[${''.padStart(done, '=')}${''.padStart(left, '-')}] ${percent}%`
return str
}
接下来我们开始进入到爬虫的主要逻辑
// 因为我们需要用到大量的 await 语句,因此在外层包裹一个 async function
async function main() {
// Do something
}
main()
// 进入代码的主逻辑
async function main() {
// 首先通过Puppeteer启动一个浏览器环境
const browser = await puppeteer.launch()
log(chalk.green('服务正常启动'))
// 使用 try catch 捕获异步中的错误进行统一的错误处理
try {
// 打开一个新的页面
const page = await browser.newPage()
// 监听页面内部的console消息
page.on('console', msg => {
if (typeof msg === 'object') {
console.dir(msg)
} else {
log(chalk.blue(msg))
}
}) // 打开我们刚刚看见的淘宝页面
await page.goto('https://s.taobao.com/search?q=gtx1080&imgfile=&js=1&stats_click=search_radio_all%3A1&initiative_id=staobaoz_20180416&ie=utf8')
log(chalk.yellow('页面初次加载完毕'))
// 使用一个 for await 循环,不能一个时间打开多个网络请求,这样容易因为内存过大而挂掉
for (let i = 1; i <= TOTAL_PAGE; i++) {
// 找到分页的输入框以及跳转按钮
const pageInput = await page.$(`.J_Input[type='number']`)
const submit = await page.$('.J_Submit')
// 模拟输入要跳转的页数
await pageInput.type('' + i)
// 模拟点击跳转
await submit.click()
// 等待页面加载完毕,这里设置的是固定的时间间隔,之前使用过page.waitForNavigation(),但是因为等待的时间过久导致报错(Puppeteer默认的请求超时是30s,可以修改),因为这个页面总有一些不需要的资源要加载,而我的网络最近日了狗,会导致超时,因此我设定等待2.5s就够了
await page.waitFor(2500)
// 清除当前的控制台信息
console.clear()
// 打印当前的爬取进度
log(chalk.yellow(formatProgress(i)))









