海量数据爬虫效率优化之:多数据插入

今天是海量数据爬虫效率优化的最后一篇。在做爬虫数据插入时,不可缺少的步骤是数据的持久化,我们需要把采集到的数据插入到数据库中。

我们通常会用同步的方式,经常会依据采集到的记录一个一个的插入数据表中,但是在效率上却常常没有发挥全部性能。

比如我们的一个场景是抓取10个店铺,每个店铺采集所有商品插入数据表中,以NodeJS写的爬虫为例:

let shopList = getShopList()
for(let i = 0; i < shopList.length; i++){
    let shop = await shopList[i]
    let items = await getItems(shop)
    for(j = 0; j < items.length; j++){
        let item = items[j]
        await Model.create(item) //插入一条商品进表
    }
}

这是一个简单的典型的爬虫脚本,似乎很自然且很清晰。但是当我们需要处理几万个店铺,每个店铺有几百个商品时,相当于我们需要对数据表操作几百万次!

其实我们发现对数据表的操作其实有一次插入多条数据的sql语句,而以我用的数据库操作ORM--Sequelize为例,其实也有插入多条数据的API,这时我们可以这么对爬虫脚本进行改造:

let shopList = getShopList()
for(let i = 0; i < shopList.length; i++){
    let shop = await shopList[i]
    let items = await getItems(shop)
    let itemsList = []
    for(j = 0; j < items.length; j++){
        let item = items[j]
        itemsList.push(item)
    }
    await Model.bulkCreate(item) //插入一条商品进表
}

当我们需要对爬下的每条商品信息做完清洗后,可以先暂存到一个数组里,待爬完一个店铺的所有商品后,再用一条语句同时将数据上传。

经过这样的改造,爬虫脚本效率就高多了,对数据库的操作也缓和很多。当然,也要注意多条数据插入的API限制,如果数据实在过大,可以分批做插入。