zoukankan      html  css  js  c++  java
  • Node爬取简书首页文章

    Node爬取简书首页文章

    博主刚学node,打算写个爬虫练练手,这次的爬虫目标是简书的首页文章

    流程分析

    • 使用superagent发送http请求到服务端,获取HTML文本
    • 用cheerio解析获得的HTML文本,本例将解析简书首页20篇文章的基本信息
    • 使用mysql模块把解析出的数据写入本地数据库存储

    第三方模块

    superagent

    superagent是一个优雅又轻量级的网络请求API,类似于Python中的requests。官方文档在这里

    $ npm install superagent
    

    基本用法

    Post请求

    request
      .post('url')
      .send({ name: 'Manny', species: 'cat' }) //发送的数据
      .set('X-API-Key', 'foobar') // set用来设置http请求头
      .set('Accept', 'application/json')
      .end(function(err, res){ // 请求发送结束后监听服务器相应,注册回调函数
        if (err || !res.ok) {
          alert('Oh no! error');
        } else {
          alert('yay got ' + JSON.stringify(res.body));
        }
      });
    
    // 链式写法
    request.post('/user')
        .send({ name: 'tj' })
        .send({ pet: 'tobi' })
        .end(callback)
    

    Get请求

    request
      .get('url')
      .query({ query: 'Manny', range: '1..5', order: 'desc' }) //加查询参数
      .end(function(err, res){
          // do something
      });
    
    // 链式写法
    request
      .get('/querystring')
      .query('search=Manny')
      .query('range=1..5')
      .end(function(err, res){
      });
    

    cheerio

    cheerio是一个快速优雅的node解析库,可以再服务器端使用jQuery的方法完成dom操作,官方文档在这里

    在本爬虫中,用于完成html解析查询的工作

    $ npm install cheerio
    

    基本用法

    const cheerio = require('cheerio')
    const $ = cheerio.load('<h2 class="title">Hello world</h2>') //导入html
    // 查询并修改dom树内容
    $('h2.title').text('Hello there!')
    $('h2').addClass('welcome')
    

    mysql

    mysql用于最后数据的写入,执行SQL插入工作,只执行sql插入

    $ npm install mysql
    

    目标分析

    我们用firefox的开发者工具查看网页,目标是一个note-list下面的20个li,每个li是一篇文章,我们只要遍历20篇文章并且对于每个节点的内容进行解析即可

    实现代码

    const superagent = require('superagent')
    const cheerio = require('cheerio')
    const util =require('util')
    const mysql = require('mysql')
    
    // 定义爬取对象
    const reptileUrl = 'http://www.jianshu.com/'
    // 创建mysql数据库连接
    const connection = mysql.createConnection({
        host:'localhost',
        user:'***',
        password:'***',
        database:'jianshu'
    })
    connection.connect()
    //发送请求
    superagent.get(reptileUrl).end(function (err, res) {
        // 错误拦截
        if (err){
            throw err
        }
        else{
            // res.text是响应的原始html
            var $ = cheerio.load(res.text)
            var articleList = $("#list-container .note-list li")
            articleList.each(function(_, item){
                //获取当前item
                var _this = $(item)
                // 文章名
                var title = _this.find('.title').text().trim()
                // 作者
                var nickname = _this.find('.nickname').text().trim()
                // 摘要
                var abstract = _this.find('.abstract').text().trim()
                // 分类, 有些未分类的就分到『其他』
                var tag = _this.find('.collection-tag').text().trim()||"其他"
                // 阅读量
                var read = _this.find('.ic-list-read').parent().text().trim()
                // 评论数
                var comment = _this.find('.ic-list-comments').parent().text().trim()
                // 点赞数
                var like = _this.find('.ic-list-like').parent().text().trim()
    
    
                // 解析后把数据写入数据库
                var base = "insert into articles " +
                    "(title, nickname, abstract, tag, readNum, commentNum, likeNum)" +
                    "values(%s,%s,%s,%s,%s,%s,%s)"
                var sql = util.format(base,
                    "'"+title+"'",
                    "'"+nickname+"'",
                    "'"+abstract+"'",
                    "'"+tag+"'",
                    "'"+read+"'",
                    "'"+comment+"'",
                    "'"+like+"'")
                connection.query(sql, function (error, results) {
                    if (error){
                        console.error(error)
                    }
                    else{
                        console.log(sql)
                    }
                })
            })
            // 关闭数据库连接
            connection.end()
        }
    })
    

    运行结果

    小结

    感觉node编程就要经常考虑异步和回调,思维方式与Python,Java不同。例如get是一个异步的行为,之前博主按照惯例在最后关闭数据库连接,结果竟然在服务器响应之前数据库连接已经断开,导致后面数据写入出错。

    填node的坑还是任重道远啊……

  • 相关阅读:
    [字符串] 洛谷 P2264 情书
    [IDA*] 洛谷 P2324 骑士精神
    [Tarjan] 洛谷 P2746 校园网
    [dp][瞎搞] 洛谷 P2501 数字序列
    [虚树][lca][dfs] 洛谷 P3233 世界树
    [斜率优化][dp] 洛谷 P3648 序列分割
    [带修莫队] Bzoj 2120 数颜色
    [数学][组合数] Jzoj P4257 着色
    [贪心][前缀和] Jzoj P4256 平均数
    [dfs] 洛谷 P2535 收集资源
  • 原文地址:https://www.cnblogs.com/fanghao/p/7821237.html
Copyright © 2011-2022 走看看