简单的用NodeJS抓取腾讯电视剧数据的实操

事实上这是个对我超简单,并且熟练得不能再熟练的数据爬取,整个代码撸完没超过20分钟。

上个星期某个晚上,女票在弄工作上的事:要把腾讯上的连续剧做分析。

地址 http://v.qq.com/x/list/tv

图片

腾讯上只有简单的筛选,并且要查看相关连续剧情况还得搜索或翻页,于是她问我能不能帮到什么?而我在弄完后将实战中一些小tips和小坑给写一下。

源码放在了我的github上 https://github.com/18978909244/qq-tv-serial

这里主要讲一下思路

首先分析目标网址

点击2018筛选的url是 http://v.qq.com/x/list/tv?offset=0&year=4060,翻1页是http://v.qq.com/x/list/tv?offset=30&year=4060

那很明显offset是偏移量,每页30,而year是id吧(不过很奇怪为什么2018年不直接用2018) 至此写一个数组存起每一个年份的id和最大页数便可,用来遍历爬取的网址

{
  year: 2018, //用于文件名
  id: 4060, //id
  maxPage: 36 //最大页数
},
{
  year: 2017,
  id: 2017,
  maxPage: 36
}

爬取数据并处理

用到的库是axios和cheerio,并且采用es7最新的async/await的语法来处理异步请求,每一个年份的每一页作为一个异步操作完成后再进入下一个请求。

axios用来发起请求,具体没什么好讲的,不过要注意的是经测试,腾讯视频对同一IP连续发起请求过于频繁有相应的反爬措施,这也是写爬虫脚本时要注意的一点,我第一次尝试时在中间某一时间会发现IP请求被封,等待5分钟后才可以重新发起请求。所以我加了一个sleep函数来增加异步请求的间隔。

而cheerio是服务端使用的和jQuery的API一样的库去操作和获取DOM,只要分析节点并遍历获取每一页相应的数据即可。

/**
 * 爬虫核心方法
*/
async () => {
  let urls = common.urls //获取url数据
  console.log(`task start!`)
  for (let i = 0; i < urls.length; i++) {
    let all = [] //存放爬到的数据
    for (let j = 0; j < urls[i].maxPage; j++) {
      console.log(`开始${urls[i].year}第${j+1}页`)
      await common.sleep(2)
      let data = await common.fetchPage(urls[i].id, j)
      let lists = handleHtml(data)  //handleHtml是处理数据的方法
      lists = lists.map(item => {
        item.year = urls[i].year
        return item
      })
      all = [...all, ...lists]
    }
    fs.writeFileSync(path.join(__dirname, `./dist/${urls[i].year}.txt`), JSON.stringify(all)) //把数据写入并存储
    console.log(`${urls[i].year}.txt saved!`)
  }
  console.log('task end!')
}

数据存储

在上面的核心方法里,在每个年份都爬完后,还需要使用Node原生操作文件的能力将JSON数据写入文本中,剩下的就是把抓到的数据给女票来做数据分析的活儿了。在网上找了个工具,是把json数据转成excel格式,所以就不需要专门写相应导出成excel格式的方法了。毕竟没几个文件,没到海量操作没必要什么都自己实现。

至此,一个简单的爬虫做完。这个相对还是特别简单的,因为连相应的访问授权都不需要处理。

其实,爬虫是个相对好玩的事儿,不光在生活中还是工作中都可以用来解决很多问题和做很多很有趣的事儿。

如果你有生活或工作中隐约感觉能用代码解决的,欢迎留言或私我,好玩有用的话我很愿意帮忙。