web实验项目

实验项目要求

1.核心需求:
1)选取3-5个代表性的新闻网站(比如新浪新闻、网易新闻等,或者某个垂直领域权威性的网站比如经济领域的雪球财经、东方财富等,或者体育领域的腾讯体育、虎扑体育等等)建立爬虫,针对不同网站的新闻页面进行分析,爬取出编码、标题、作者、时间、关键词、摘要、内容、来源等结构化信息,存储在数据库中。
2) 建立网站提供对爬取内容的分项全文搜索,给出所查关键词的时间热度分析。
2.必须采用Node.JS实现网络爬虫
3.必须采用Node.JS实现查询网站后端,HTML+JS实现前端(尽量不要使用任何前后端框架)

  • [√] 爬取标题等结构化信息,存储在数据库中
  • [√] 建立网站提供分项全文搜索
  • [?] 给出所查关键词的时间热度分析
  • [√] 采用Node.JS实现网络爬虫
  • [√] 采用Node.JS实现查询网站后端
  • [√] HTML+JS实现前端
终极要求(4/27改)

1、完成对数据库中爬取数据内容或者标题的搜索功能,搜索结果以表格的形式展示在前端页面中(√)
2、完成对搜索内容的时间热度分析,展示某一关键词的条数(形式可以发挥)(?)
3、网站页面设计简洁美观(√)
4、详细描述目标网站的分析过程;详细描述爬虫整体结构、使用的工具包、数据库设计;详细描述搜索网站前后端的设计;图文展示实现的效果(√)

提示

var schedule = require('node-schedule')  //设置定时爬虫
var myIconv = require(‘iconv-lite’)  //编码转换 GB2312到UTF-8
var fs = require(‘fs’);  //保存到本地文件
var mysql = require(‘mysql’);  //保存到mysql数据库
npm install elasticsearch  //可以用elasticsearch构建爬取数据的索引

一些可以应用于爬虫的things:

  1. 利用数据库存储爬取的数据(MySQL)
  2. 爬取新闻页面之前先查询数据库,是否该url已经爬取过了
  3. 使用node-schedule模块,设置定时工作
  4. 用网页发送请求到后端进行查询
  5. 用express构建网站,访问mysql
  6. 用表格显示所查询的结果
  7. something else(如,分析有多个种子页面的情况下设计爬虫)

具体实现过程(一)

我的第一个爬虫(简陋的雪球)

  1. 分析种子页面,找到要爬取的a链接
  2. 进入新闻页面,找出所爬取的源代码
  3. 得到思路:读取种子页面、分析所有新闻链接、爬取新闻链接中的内容、分析内容,解析出结构化数据、将结构化数据保存到本地,再将数据保存到数据库中,通过构建网页清晰地呈现

(PS:选取了“雪球”,主要是因为它的代码比较简单,然后大致的框架仍是基于老师的教学代码)

  1. 分析网站源代码结构,通过逐一检查,发现:所有的帖子都是在class=AnonymousHome_a__placeholder_3RZ的目录下
    源代码
  2. 进一步分析目录下的a链接中的内容,发现,种子页面的网址(seedURL)+ href = 即为二级网站的网址(url)
    源代码解析
  3. 找到二级网站中,标题、摘要、来源、日期、作者对应的html语言(后期定稿时截图,故有些细节不完全一致)
    对应ing
初稿

(写在本地)

var source_name = "雪球网";
var myEncoding = "utf-8";
var seedURL = 'https://xueqiu.com';

var seedURL_format = "$('.AnonymousHome_a__placeholder_3RZ')";
var keywords_format = " $('meta[name=\"keywords\"]').eq(0).attr(\"content\")";
var title_format = "$('article_bd_title').text()";
var desc_format = " $('meta[name=\"description\"]').eq(0).attr(\"content\")";
var source_format = "$('source').text()";
var date_format = "$('time').text()";
var author_format = "$('data_screenname').text()";

var fs = require('fs');
var myRequest = require('request')
var myCheerio = require('cheerio')
var myIconv = require('iconv-lite')
require('date-utils');

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'
}

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

request(seedURL, function(err, res, body) { 
    var html = myIconv.decode(body, myEncoding);
    var $ = myCheerio.load(html, { decodeEntities: true }); 

    var seedurl_news;

    try {
        seedurl_news = eval(seedURL_format);
    } catch (e) { console.log('url列表所处的html块识别出错:' + e) };

    seedurl_news.each(function(i, e) {
        var myURL = "";
        try {
            var href = "";
            href = $(e).attr("href");
            if (typeof(href) == "undefined") { 
                return true;
            }
            myURL = seedURL + href;
        } catch (e) { console.log('识别种子页面中的新闻链接出错:' + e) }
        newsGet(myURL); 
    });
});

function newsGet(myURL) {
    request(myURL, function(err, res, body) {
        var myhtml = myIconv.decode(body, myEncoding); 
        var $ = myCheerio.load(myhtml, { decodeEntities: true });
        console.log("转码读取成功:" + myURL);
        
        var fetch = {};
        fetch.url = myURL;
        fetch.title = "";
        fetch.source_name = source_name;
        fetch.source_encoding = myEncoding; 
        fetch.date = "";
        
        if (keywords_format == "") fetch.keywords = source_name; 
        else fetch.keywords = eval(keywords_format);
        if (title_format == "") fetch.title = ""
        else fetch.title = eval(title_format); 
        if (desc_format == "") fetch.desc = fetch.title;
        else fetch.desc = eval(desc_format).replace("\r\n", ""); 
        if (date_format == "") fetch.date = ""
        else fetch.date = eval(date_format); 
        if (author_format == "") fetch.author = source_name; 
        else fetch.author = eval(author_format);
        if (source_format == "") fetch.source = fetch.source_name;
        else fetch.source = eval(source_format).replace("\r\n", ""); 

        console.log('date: ' + fetch.date);
        console.log(myURL);


        var filename = source_name + "_" + myURL.substr(myURL.lastIndexOf('/') + 1) + ".json";
        fs.writeFileSync(filename, JSON.stringify(fetch));
    });

    
}
代码解析
  1. 具体实现步骤:定义要访问的网站;引入必要的模块;定义新闻页面里具体的元素的读取方式;定义哪些url可以作为新闻页面(使用正则表达式)
  2. 其中,例如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}日)/使用了正则表达式,详见
  3. 构造了一个模仿浏览器的request(其实request包npm上有,老师给了就直接用了)
  4. 在request函数中读取页面,解析出种子页面中所有的class=AnonymousHome_a__placeholder_3RZ链接
  5. 通过each语句,遍历种子页面中的所有class=AnonymousHome_a__placeholder_3RZ链接,并通过规整化所有链接,(后面爬取的a链接时,需要通过正则表达式来判断,如果符合我们设定的新闻URL的正则表达式才爬出)
  6. 再定义了newsGet函数,读取具体的新闻页面(也就是俗称的二级网站),并构造一个空的fetch对象用于存储数据(里面调用的request函数和种子页面的调用雷同)
  7. 将读取的新闻页面中需要的元素保存到fetch对象中
  8. 最后,将fetch对象保存在文件中(后面mysql中的fetch即为此物)
  9. 执行该文件,即可创建出多个符合条件的新闻文件
  10. cheerio是一个Node.JS的模块库,可以从HTML的片段中构建DOM结构,然后提供像jQuery一样的CSS选择器查询,通过npm install cheerio安装该模块
  11. request也是一个Node.JS的模块库,可以轻松地完成HTTP请求,同理使用npm install request安装
  12. 通过npm官网查看每个模块的相关资料
    cheerio
    request
    (ps:此处npm安装略,官网下载)
  13. url是指一个网址,callback就是一个回调函数
  14. var定义全局变量;let定义局部变量
  15. encoding:使用null时,传递二进制数据;其他任何值将传递给toString;此处我们需要获得二进制数据
  16. headers:HTTP头,一般设为null
  17. 必要时,为了防止对方屏蔽我们爬虫。可以伪装成网页
    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' }
  18. decode 将缓冲区编码转换为js字符串
  19. try-catch
    try { //在这里运行代码 抛出错误 } catch(err) { //在这里处理错误 }
    后半句相当于(如下代码为基础学习时所写)
if (err || res.statusCode != 200) {
		console.error(err);
		console.error(res.statusCode);
		return;
	}
  1. eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。此处计算的是含有a标签的链接;后面是为了将源代码中的属性交给定义的变量
  2. each的参数function(index,element)
  3. toLowerCase() 方法用于把字符串转换为小写。
  4. indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。代码中是为了判断以’http://'和’https://'开头的链接(若以//开头,要自行加入http:)
  5. substr() 方法可在字符串中抽取从 start 下标开始的指定数目的字符,语法:stringObject.substr(start,length)
  6. lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。
  7. 创建date对象——var myDate=new Date()//Date 对象会自动把当前日期和时间保存为其初始值。
  8. exec() 方法用于检索字符串中的正则表达式的匹配。领用此函数检查正则表达式
  9. replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
  10. MySQL的一些语法:
    mysql_query() 函数执行一条 MySQL 查询。语法:mysql_query(query,connection)其中,query必需,规定要发送的SQL查询,查询字符串不能以分号结束;connection可选,规定SQL连接标识符,如果未规定,则使用上一个打开的链接
  11. 关于Express脚手架的搭建:
    在配置环境的过程中发现,要实现在前端进行关键词的搜索,只需要更改为mysql.js中数据库的名字(前提是完成一次脚手架的搭建),即可完成简易地搭建
运行结果

看似正确,实际不对
对照每一个爬出的结果,title、date、author、source为空

订正部分
var source_format = "$('.source').text()";
var date_format = "$('.time').text()";
var author_format = "$('.data_screenname').text()";

错误原因
  • id=“pubtime_baidu” 在js中写为#pubtime_baidu
  • class=“left_zw” 在js中写为.left_zw;
  • 另外,关于网址为什么没有最后的“/”,连接seedURL和href的时候也会自动加上/
polish(仅显示修改部分)

(存入数据库)

var mysql = require('./mysql.js');

seedget();

function seedget() {
    request(seedURL, function(err, res, body) {
        var html = myIconv.decode(body, myEncoding);
        var $ = myCheerio.load(html, { decodeEntities: true });
        
        var seedurl_news;

        try {
            seedurl_news = eval(seedURL_format);
        } catch (e) { console.log('url列表所处的html块识别出错:' + e) };

        seedurl_news.each(function(i, e) { 
            var myURL = "";
            try {
                var href = "";
                href = $(e).attr("href");
                if (href == undefined) return true;
                myURL = seedURL + href; 
            } catch (e) { console.log('识别种子页面中的新闻链接出错:' + e) }

            var fetch_url_Sql = 'select url from fetches where url=?';
            var fetch_url_Sql_Params = [myURL];
            mysql.query(fetch_url_Sql, fetch_url_Sql_Params, function(qerr, vals, fields) {
                if (vals.length > 0) {
                    console.log('URL duplicate!')
                } else newsGet(myURL); 
            });
        });
    });
};

function newsGet(myURL) { 
    request(myURL, function(err, res, body) { 
        var fetchAddSql = 'INSERT INTO fetches(url,source_name,source_encoding,title,' +
            'keywords,author,date) VALUES(?,?,?,?,?,?,?,?,?)';
        var fetchAddSql_Params = [fetch.url, fetch.source_name, fetch.source_encoding,
            fetch.title, fetch.keywords, fetch.author, fetch.date];

        mysql.query(fetchAddSql, fetchAddSql_Params, function(qerr, vals, fields) {
            if (qerr) {
                console.log(qerr);
            }
        }); 
    });
}

//借助MySQL进行存储,代码运行结果显示,sql能够显示所爬取的信息,但是在MySQL中无法找到对应的爬取内容,在助教的指导下设置断点查看数据:(
运行结果
重新建立了一个crawl2后,发现其中的fetches为空,且程序会持续running,无法自动停下
后来数据结构代码也遇到了同样的问题,好像是因为误删了vscode的配置,呜呜呜,环境配置一直都好迷啊
代码改进中……

最终代码
var source_name = "雪球网";
var myEncoding = "utf-8";
var seedURL = 'https://xueqiu.com';

var seedURL_format = "$('.AnonymousHome_a__placeholder_3RZ')";
var keywords_format = " $('meta[name=\"keywords\"]').eq(0).attr(\"content\")";
var title_format = "$('title').text()";
var desc_format = " $('meta[name=\"description\"]').eq(0).attr(\"content\")";
var source_format = "$('.source').text()";
var date_format = "$('.time').text()";
var author_format = "$('.data_screenname').text()";

var fs = require('fs');
var myRequest = require('request');
var myCheerio = require('cheerio');
var myIconv = require('iconv-lite');
require('date-utils');
var mysql = require('./mysql.js');

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'
}

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

seedget();

function seedget() {
    request(seedURL, function(err, res, body) {
        var html = myIconv.decode(body, myEncoding);
        var $ = myCheerio.load(html, { decodeEntities: true });
        
        var seedurl_news;

        try {
            seedurl_news = eval(seedURL_format);
        } catch (e) { console.log('url列表所处的html块识别出错:' + e) };

        seedurl_news.each(function(i, e) { 
            var myURL = "";
            try {
                var href = "";
                href = $(e).attr("href");
                if (href == undefined) return true;
                myURL = seedURL + href; 
            } catch (e) { console.log('识别种子页面中的新闻链接出错:' + e) }

            var fetch_url_Sql = 'select url from fetches where url=?';
            var fetch_url_Sql_Params = [myURL];
            mysql.query(fetch_url_Sql, fetch_url_Sql_Params, function(qerr, vals, fields) {
                if (vals.length > 0) {
                    console.log('URL duplicate!')
                } else newsGet(myURL); 
            });
        });
    });
};

function newsGet(myURL) { 
    request(myURL, function(err, res, body) { 
        var myhtml = myIconv.decode(body, myEncoding); 
        var $ = myCheerio.load(myhtml, { decodeEntities: true });
        console.log("转码读取成功:" + myURL);
        
        var fetch = {};

        fetch.title = "";
        fetch.url = myURL;
        fetch.source_name = source_name;
        fetch.source_encoding = myEncoding; 
        fetch.date = "";

        if (keywords_format == "") fetch.keywords = source_name; 
        else fetch.keywords = eval(keywords_format);

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

        if (date_format == "") fetch.date = ""
        else fetch.date = eval(date_format); 
        
        console.log('date: ' + fetch.date);
        
        if (author_format == "") fetch.author = source_name; 
        else fetch.author = eval(author_format);

        if (source_format == "") fetch.source = fetch.source_name;
        else fetch.source = eval(source_format).replace("\r\n", ""); 

        if (desc_format == "") fetch.desc = fetch.title;
        else fetch.desc = eval(desc_format).replace("\r\n", ""); 

        var fetchAddSql = 'INSERT INTO fetches(title,url,source_name,source_encoding,' +
            'keywords,author) VALUES(?,?,?,?,?,?)';
        var fetchAddSql_Params = [fetch.title, fetch.url, fetch.source_name, fetch.source_encoding, fetch.keywords, fetch.author];

        mysql.query(fetchAddSql, fetchAddSql_Params, function(qerr, vals, fields) {
            if (qerr) {
                console.log(qerr);
            }
        }); 
    });
}
运行结果

!
(PS:因为是帖子,title包括了回复的内容,有些累赘,将在下一次的代码中尝试删减不要的成分,而且该代码貌似不能自动停止搜索,我也是后来同学提醒才知道)

在老师的提示下搭建express脚手架

脚手架搭建

创建了一个search_site文件,然后在其中的index.js中写入自己的代码;在public中创建一个search.html网页前端,并在该文件中添加好对应的音频和图片资料。(后一个爬虫的呈现)

最后结果

脚手架展示

数据总量改进(4/27改)

var seedURL_format = "$('a')";
var url_reg = /\/(\d{10})\/(\d{9})/;

爬虫数据
说明:因为只是爬取数据的数量问题,故没有展示前端呈现的模样,最完整的前端在下一个程序……

内容小结

虽然爬取的网页有限,而且由于网页本身的限制,爬取的内容比较冗余,但至少是向前迈进了一小步,每一次小小的成功都会让我倍感鼓舞,并继续探索,然后再不断进步。

具体实现过程(二)

我的第二个爬虫(完整的东方财富网)

代码
var fs = require('fs');
var myRequest = require('request');
var myCheerio = require('cheerio');
var myIconv = require('iconv-lite');
require('date-utils');
var mysql = require('./mysql.js');

var sourc_name = "东方财富网";
var myEncoding = "utf-8";
var seedURL = 'https://www.eastmoney.com/';

var seedURL_format = "$('a')";
var keywords_format = " $('meta[name=\"keywords\"]').eq(0).attr(\"content\")";
var title_format = "$('title').text()";
var date_format ="";// "$('.time').text()";
//var author_format = "$('#editor_baidu').text()";编辑名为代号,没有意义
var content_format = "$('#ContentBody').text()";
var desc_format = " $('meta[name=\"description\"]').eq(0).attr(\"content\")";
var source_format = "$('.em_media').text()";
var url_reg = /\/(\d{18}).html/;
//var regExp = /((\d{4}|\d{2})(\-|\/|\.)\d{1,2}\3\d{1,2})|(\d{4}年\d{1,2}月\d{1,2}日)/

//防止网站屏蔽我们的爬虫
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,
        //proxy: 'http://x.x.x.x:8080',
        headers: headers,
        timeout: 10000 //
    }
    myRequest(options, callback)
};

seedget();

function seedget() {
    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);
        } catch (e) { console.log('url列表所处的html块识别出错:' + e) };
        seedurl_news.each(function(i, e) { //遍历种子页面里所有的a链接
            var myURL = "";
            try {
                //得到具体新闻url
                var href = "";
                href = $(e).attr("href");
                if (href == undefined) return;
                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);

            var fetch_url_Sql = 'select url from fetches where url=?';
            var fetch_url_Sql_Params = [myURL];
            mysql.query(fetch_url_Sql, fetch_url_Sql_Params, function(qerr, vals, fields) {
                if (vals.length > 0) {
                    console.log('URL duplicate!')
                } else newsGet(myURL); //读取新闻页面
            });
        });
    });
};

function newsGet(myURL) { //读取新闻页面
    request(myURL, function(err, res, body) { //读取新闻页面
        //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();

        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);
/*        {fetch.publish_date = regExp.exec(fetch.publish_date)[0];
        fetch.publish_date = fetch.publish_date.replace('年', '-')
        fetch.publish_date = fetch.publish_date.replace('月', '-')
        fetch.publish_date = fetch.publish_date.replace('日', '')
        fetch.publish_date = new Date(fetch.publish_date).toFormat("YYYY-MM-DD");}
*/
/*        if (author_format == "") fetch.author = source_name; //eval(author_format);  //作者
        else fetch.author = eval(author_format);
*/
        if (content_format == "") fetch.content = "";
        else fetch.content = eval(content_format).replace("\r\n" + fetch.author, ""); //内容,是否要去掉作者信息自行决定

        if (source_format == "") fetch.source = fetch.source_name;
        else fetch.source = eval(source_format).replace("\r\n", ""); //来源

        if (desc_format == "") fetch.desc = fetch.title;
        else fetch.desc = eval(desc_format).replace("\r\n", ""); //摘要    

/*         var filename = source_name + "_" + (new Date()).toFormat("YYYY-MM-DD") +
             "_" + myURL.substr(myURL.lastIndexOf('/') + 1) + ".json";
        // 存储json
         fs.writeFileSync(filename, JSON.stringify(fetch));
*/
        var fetchAddSql = 'INSERT INTO fetches(url,source_name,source_encoding,title,' +
            'keywords,publish_date,crawltime,content) VALUES(?,?,?,?,?,?,?,?)';
        var fetchAddSql_Params = [fetch.url, fetch.source_name, fetch.source_encoding,
            fetch.title, fetch.keywords,fetch.publish_date,
            fetch.crawltime.toFormat("YYYY-MM-DD HH24:MI:SS"), fetch.content
        ];

        //执行sql,数据库中fetch表里的url属性是unique的,不会把重复的url内容写入数据库
        mysql.query(fetchAddSql, fetchAddSql_Params, function(qerr, vals, fields) {
            if (qerr) {
                console.log(qerr);
            }
        }); //mysql写入
    });
}

(思路过程大致一致,因此不再一一赘述)

结果

express呈现形式

前端设计

<!DOCTYPE html>
<html>
<header>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</header>

<head>
    <style type="text/css">
    body
    {background-image:
    url("images/14.jpg");
    }
    p{
        color:red;
    }
    </style>
</head>

<body>
    <Embed src="Floating.mp3",width="0"height="0"AUTOSTART="TRUE│false" LOOP="TRUE"></Embed>
     <p>
        <form>
            <br> 标题:<input type="text" name="title_text">
            <input class="form-submit" type="button" value="查询">
        </form>
        <div class="cardLayout" style="margin: 10px 0px">
            <table width="100%" id="record2"></table>
        </div>
    
    </p>
    <script>
        $(document).ready(function() {
            $("input:button").click(function() {
                $.get('/process_get?title=' + $("input:text").val(), function(data) {
                    $("#record2").empty();
                    $("#record2").append('<tr class="cardLayout"><td>url</td><td>source_name</td>' +
                        '<td>title</td><td>author</td><td>publish_date</td></tr>');
                    for (let list of data) {
                        let table = '<tr class="cardLayout"><td>';
                        Object.values(list).forEach(element => {
                            table += (element + '</td><td>');
                        });
                        $("#record2").append(table + '</td></tr>');
                    }
                });
            });

        });
    </script>
</body>

</html>

啊啊啊啊啊啊,前两周的时候就一直在研究html的语法,后来得知爬虫主要是用js写,然后html和css只起了锦上添花的功能,就放下了一段时间,这次也是临时再将知识回顾,做了个简单的背景和背景音乐;
那个颜色不知道怎么的就一直改不来,害
咦,放大后为什么分块了?!往下滑为什么也分块了?!还不会做动图wuwuwu

后来将细节进行了改动

<head>
    <title>
        东方财富网爬虫
    </title>
</head>

<body background="images/17.jpeg"
    style="background-repeat: no-repeat;
            background-size:100% 100%;
            background-attachment:fixed;">
    <h1>爬虫……</h1>
    <Embed src="Floating.mp3",width="0"height="0"AUTOSTART="TRUE│false" LOOP="TRUE"></Embed>

效果呈现

效果呈现

爬虫代码运行中常出现的错误

error1
(PS:上述错误出现在output之后,不影响爬虫结果,但以我浅薄的知识水平无法解决,还请各路dalao解答
后来问老师过后,可能是格式的问题,把date注释掉就可以了
这也是为什么我的前端呈现中date那一栏为null啊,)

附各种文件

mysql.js
index.js
fetches.sql

写在最后

只写过一学期C语言的前端开发小白,从零开始,磕磕绊绊,主要根据老师的教学逐步推进,以此记录开发全程!
至于选择了两个财经类网站,纯属巧合,最近恰好对理财基金比较关注~~(捂脸)~~
此外,在开发过程中,发现一开始那种抱着掌握所有的基础知识再开始着笔的方式,完全不适合我,故再后期以看代码为主,重点分析他人代码,然后再进行对应地搜索,以此获得了许多的基础知识。
(部分代码来源于教学,刚开始较盲目的时候观看多位老师的视频,后期也主要以修改老师代码为主)
另外,由于刚开始的思路跟老师最终的要求不同,整篇文章几乎重新更改,很多逻辑、排版也没有仔细推敲,还拖了这么久(呜呜呜)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值