Node.js期中爬虫实验项目

这篇博客详细记录了使用Node.js进行爬虫的期中作业过程,从基础概念到实际操作,包括前端后端的区别、Web组成、Node.js介绍,以及爬虫项目的准备、正则表达式学习、不同网站的爬取分析和数据存储。通过Navicat展示数据,实现了在浏览器中显示爬取结果,并进行了前端美化,包括词云热度分析。博主分享了学习心得,强调了实践的重要性。
摘要由CSDN通过智能技术生成

期中作业要求

在这里插入图片描述

基础概念引入

前后端
前台:呈现给用户的视觉和基本的操作。
后台:用户浏览网页时,我们看不见的后台数据跑动。后台包括前端、后端。
前端:对应html、css、javascript 等网页语言作用在前端网页。
后端:对应jsp、javaBean、dao层、action层和service层的业务逻辑代码。(包括数据库)

Web
定义:Web 是一种基于超文本和HTTP协议的、全球性的、动态交互的、跨平台的分布式图形信息系统,是建立在Internet上的一种网络服务。
组成部分:
结构标准语言(html):存放网页元素。决定网页结构和内容(决定看到什么),相当于人的身体(描述类)
表现标准语言(css):对元素的样式进行设置,例如宽度、高度、位置、字体。决定网页呈现给用户的模样(决定好不好看),相当于化妆(描述类)
行为标准语言(javascript):对元素取值,动态的改变。实现业务逻辑和页面控制(决定功能),相当于人的各种动作(编程类)

Node.js
Node.js 就是运行在服务端的 JavaScript。
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google Chrome的V8引擎,V8引擎执行JavaScript的速度非常快,性能非常好。
node.js属于异步编程:发送初始请求,没有得到响应的时候可以继续发送请求,如果第一个发送的请求得到响应了,就返回。即同时执行多个。
而如php,java是同步,必须得到响应之后才能继续发送请求

检查和源码的区别
1.查看源代码:他人服务器发送到浏览器的原封不动的代码,也就是最原始的代码。在源代码中找不到的代码,是在浏览器执行js动态生成的。
2.检查(F12):最终的html代码。即:源代码 + 网页js渲染 。

前期准备工作

安装node.js

node.js下载地址
在这里插入图片描述

安装数据库

以使用最广泛的开源数据库MySQL为例
mysql下载地址
在这里插入图片描述
数据库详细的配置可以参考我的博客

安装Navicat Premium 15

学姐推荐下载这个软件,可以使爬取的数据显示更为清晰明了

Navicat是一套快速、可靠的数据库管理工具。
Navicat下载地址
在这里插入图片描述

正则表达式学习网站

regular expressions 101
在这里插入图片描述
菜鸟教程正则表达式在线测试在这里插入图片描述

课堂示例演示

示例一(显示在终端中

代码

var myRequest=require('request')
var myCheerio=require('cheerio')
var myURL='http://www.ecnu.edu.cn/e5/bc/c1950a255420/page.htm'

function request(url,callback){
   
    var options={
   
        url:url,
        encoding:null,
        headers:null
    }
    myRequest(options,callback)
}

request(myURL,function(err,res,body){
   
    var html=body
    var $=myCheerio.load(html,{
   decodeEntities:false})
    console.log($.html())
    // html页面title的信息
    console.log('title:'+$('title').text())
    // html页面的摘要的信息
    // console.log('description:'+$('meta[name="description"]').eq(0).attr("content"))  
})

运行结果

实际现在这个网站不可访问,无法输出下列结果,但可以正常输出网页结构,即运行成功
在这里插入图片描述

示例二(保存在本地文件

流程
1、读取种子页面
2、分析出种子页面里的所有新闻链接
3、爬取所有新闻链接的内容
4、分析新闻页面内容,解析出结构化数据
5、将结构化数据保存到本地文件

代码

require引入模块。保存在本地文件的关键模块是fs。故在后续存入数据库的代码中,fs模块是可以省略的。

var fs = require('fs');//通过require引入各种包,以方便功能地实现request,fs功能是使爬取内容保存在本地,对系统文件和目录读取
var myRequest = require('request')//发送http请求
var myCheerio = require('cheerio')//获取html内容,使用jquery的方式
var myIconv = require('iconv-lite')//用于各字符集间高效的转码,编码转码gb2312到utf-8
require('date-utils');//为了解析日期的方便

获取URL(即获取要访问的网址

Uniform Resource Locator,统一资源定位器。它是万维网(www)的统一资源定位标志,即指网络地址。
URL格式一般如下:
协议类型://服务器地址[:端口号]/路径/文件名[参数=值]

var source_name = "中国新闻网";//获取url 其格式一般为“协议名+主机名/IP地址及其端口+文件路径”
var myEncoding = "utf-8";//字符编码
var seedURL = 'http://www.chinanews.com/';//目标网址中国新闻网

定义新闻元素的读取方式,即规定哪些url可有作为新闻页面,最后两行使用的是正则表达式,用于检查网页是否符合规范

正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
正则表达式语法教程

var seedURL_format = "$('a')";
var keywords_format = " $('meta[name=\"keywords\"]').eq(0).attr(\"content\")";
var title_format = "$('title').text()";
var date_format = "$('#pubtime_baidu').text()";
var author_format = "$('#editor_baidu').text()";
var content_format = "$('.left_zw').text()";
var desc_format = " $('meta[name=\"description\"]').eq(0).attr(\"content\")";
var source_format = "$('#source_baidu').text()";
var url_reg = /\/(\d{4})\/(\d{2})-(\d{2})\/(\d{7}).shtml/;
var regExp = /((\d{4}|\d{2})(\-|\/|\.)\d{1,2}\3\d{1,2})|(\d{4}年\d{1,2}月\d{1,2}日)/

构造一个模仿浏览器的request

//防止网站屏蔽爬虫
//如果爬取过于频繁,可能会被网站屏蔽,这段代码的作用是伪装成浏览器,防止被屏蔽
var headers = {
   
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36'
}

//request模块异步fetch url
function request(url, callback) {
   
    var options = {
   
        url: url,
        encoding: null,
        headers: headers,
        timeout: 10000 
    }
    myRequest(options, callback)
}

读取种子页面,解析出种子页面里所有的a herf链接

request(seedURL, function(err, res, body) {
   
    // try {
   
    //用iconv转换编码
    var html = myIconv.decode(body, myEncoding);
    //console.log(html);
    //准备用cheerio解析html
    var $ = myCheerio.load(html, {
    decodeEntities: true });
    // } catch (e) { console.log('读种子页面并转码出错:' + e) };
    var seedurl_news;
    try {
   
        seedurl_news = eval(seedURL_format);
        //console.log(seedurl_news);
    } catch (e) {
    console.log('url列表所处的html块识别出错:' + e) };

遍历种子页面里所有的a herf链接
规整化所有链接,如果满足新闻url的正则表达式就爬取

    seedurl_news.each(function(i, e) {
    
        var myURL = "";
        try {
   
            //得到具体新闻url
            var href = "";
            href = $(e).attr("href");
            if (typeof(href) == "undefined") {
     // 有些网页地址undefined
                return true;
            }
            if (href.toLowerCase().indexOf('http://') >= 0 || href.toLowerCase().indexOf('https://') >= 0) myURL = href; //http://开头的或者https://开头
            else if (href.startsWith('//')) myURL = 'http:' + href; 开头的
            else myURL = seedURL.substr(0, seedURL.lastIndexOf('/') + 1) + href; //其他

        } catch (e) {
    console.log('识别种子页面中的新闻链接出错:' + e) }

        if (!url_reg.test(myURL)) return; //检验是否符合新闻url的正则表达式
        //console.log(myURL);
        newsGet(myURL); //读取新闻页面
    });
});

读取具体的新闻页面,构造一个空的fetch对象用于存储数据

function newsGet(myURL) {
    //读取新闻页面
    request(myURL, function(err, res, body) {
    //读取具体的新闻页面,构造一个空的fetch对象用于存储数据
        //try {
   
        var html_news = myIconv.decode(body, myEncoding); //用iconv转换编码
        //console.log(html_news);
        //准备用cheerio解析html_news
        var $ = myCheerio.load(html_news, {
    decodeEntities: true });
        myhtml = html_news;
        //} catch (e) {    console.log('读新闻页面并转码出错:' + e);};

        console.log("转码读取成功:" + myURL);
        //动态执行format字符串,构建json对象准备写入文件或数据库
        var fetch = {
   };
        fetch.title = "";
        fetch.content = "";
        fetch.publish_date = (new Date()).toFormat("YYYY-MM-DD");
        //fetch.html = myhtml;
        fetch.url = myURL;
        fetch.source_name = source_name;
        fetch.source_encoding = myEncoding; //编码
        fetch.crawltime = new Date();

读取新闻页面中的元素并保存到fetch对象里

        if (keywords_format == "") fetch.keywords = source_name; // eval(keywords_format);  //没有关键词就用sourcename
        else fetch.keywords = eval(keywords_format);

        if (title_format == "") fetch.title = ""
        else fetch.title = eval(title_format); //标题

        if (date_format != "") fetch.publish_date = eval(date_format); //刊登日期   
        console.log('date: ' + fetch.publish_date);
        console.log(myURL);
        fetch.publish_date = regExp.exec(fetch.publish_date)[0];
        fetch.publish_date = fetch.publish_date.replace('年', 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值