前端设计与开发实验项目1:nodejs新闻爬虫及爬取结果的查询网站

本文介绍了一个前端设计与开发实验项目,利用Node.js实现新闻爬虫,爬取新浪财经、东方财富网和人民网的新闻,并将数据存入MySQL数据库。项目包括爬虫部分、网站部分和总结。在爬虫部分,主要涉及网页内容获取、正则表达式筛选、字段处理和数据库插入。网站部分则涵盖了搜索功能、结果展示和时间热度分析。在实施过程中,作者遇到了引号问题导致的数据库插入失败,通过处理解决了这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目要求

第一部分:爬虫部分

对三个新闻网站进行爬取:新浪财经、东方财富网、人民网。
爬虫步骤可大致分为两步:1.从网页获取需要的内容 2.对获取的内容进行处理

1.第一步:从网页获取需要的内容

这个部分中,各个网页不同,有一个便捷的方法:保存爬取到的body部分,直接搜索对应的关键词,比如:keyword,title,author等等,就可以快速定位;也可以打开开发者工具慢慢找。

  1. 新浪财经
    从新浪财经的网页中寻找规律,提取所需字段
var source_name = "新浪财经";
var domain = 'https://finance.sina.com.cn/';
var myEncoding = "utf-8";
var seedURL = 'https://finance.sina.com.cn/';

var seedURL_format = "$('a')";
var keywords_format = " $('meta[name=\"keywords\"]').eq(0).attr(\"content\")";
var title_format = "$('.main-title').text()";
var date_format = "$('.date').text()";
var author_format = " $('meta[name=\"author\"]').attr(\"content\")";
var content_format = "$('.article').text()";
var desc_format = " $('meta[name=\"description\"]').eq(0).attr(\"content\")";
var source_format = "$('.source').text()";
  1. 东方财富网
    从东方财富网的网页中寻找规律,提取所需字段
var source_name = "东方财富";
var domain = 'https://www.eastmoney.com/';
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 = "$('h1').text()";
var date_format = "$('.time').text()";
var author_format = "$('p.res-edit').text()";
var content_format = "$('.post_text p').text()";
var desc_format = "$('.b-review').text()";
var source_format = "$('p.em_media').text()";
  1. 人民网
    从人民网的网页中寻找规律,提取所需字段
var source_name = "人民网";
var domain = 'http://www.people.com.cn/';
var myEncoding = "gbk";
var seedURL = 'http://www.people.com.cn/';

var seedURL_format = "$('a')";
var keywords_format = " $('meta[name=\"keywords\"]').eq(0).attr(\"content\")";
var title_format = "$('h1').text()";
var date_format = " $('meta[name=\"publishdate\"]').eq(0).attr(\"content\")";
var author_format = "$('p.author').text()";
var content_format = "$('.box_con p').text()";
var desc_format = "$('meta[name=\"description\"]').eq(0).attr(\"content\")";
var source_format = " $('meta[name=\"source\"]').eq(0).attr(\"content\")";

2.正则化

  1. 获取文章链接
    从新闻网站中获得的很多链接可能不是站内文章链接,会引发错误,因此要使用正则化筛选。每个网站的文章链接命名规则不同,要从中找出规律。据观察:
    新浪财经:文章链接都包括“doc-”
    东方财富网:文章链接都包括“a/2020”
    人民网:文章链接都包括“2020”
  2. 通用正则表达式
    观察到有一些爬取到的内容会插入数据库失败,为了找出失败的原因,需要将爬取到的内容或sql语句写入文档存档。
    我采取的方式是以source_name+日期+title的方式作为文件名,存储爬取到的内容。当title里有空格、问号等符号时,会出错,因此进行正则化处理。
    另外,content如果有大量换行符、空格、制表符会显得很混乱,因此进行一些正则化处理。
var url_reg = /\/(\d{4})\/(\d{2})-(\d{2})\/.+\.shtml/;
var regExp = /((\d{4}|\d{2})(\-|\/|\.)\d{1,2}\3\d{1,2})|(\d{4}年\d{1,2}月\d{1,2}日)/
var reg = new RegExp(`,`,"g");
var reg1 = new RegExp('?',"g");
var reg2 = new RegExp('\n',"g");
var reg3 = new RegExp(' ',"g");
var reg4 = new RegExp('|',"g");
var reg5 = new RegExp(`“`,"g");
var reg6 = new RegExp(`”`,"g");
var reg7 = new RegExp('\t',"g");
var regf = /[\u4e00-\u9fa5]/g;

3.处理爬取到的字段

  1. 处理标题
    标题只保留汉字,实测这样存文件名时才不会报错。
    实测标题不太会是undefined,但有可能为空,需要判断一下。
    match后的形式是list,用tostring再转回字符串
if (title_format == "") fetch.title = " "
else fetch.title = eval(title_format); //标题
strtitle=fetch.title;
if (strtitle != '') fetch.title=strtitle.match(regf).toString().replace(reg,'');

2.处理日期
这样的replace一次只替换一个,把日期转换成类似“2020-04-27”的格式

if (date_format != "") fetch.publish_date = eval(date_format); //刊登日期 
if (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");
} 

3.处理内容
去掉换行符和制表符和空格,不去除的话很可能影响插入数据库。
或许有比我更高级的replace方法吧。

if (content_format == "") fetch.content = fetch.desc;
else fetch.content = eval(content_format).replace(`'`, ''); 
if (fetch.content == "") fetch.content = fetch.desc;
if (fetch.content != '' && fetch.content != undefined) {
fetch.content=fetch.content.replace(reg2,'');
fetch.content=fetch.content.replace(reg3,'');
fetch.content=fetch.content.replace(reg5,'');
fetch.content=fetch.content.replace(reg6,'');
fetch.content=fetch.content.replace(reg7,'');
}

4.写入数据库

插入成功的就保存fetch,插入失败的就保存quertstr,之后尝试手动插入数据库看看失败原因。
尝试的过程中有些手动插入可以成功,后来发现原因是引号的问题。因此替换掉title和content中的引号可以提高成功率。汉字以外的字符都有可能导致失败。
基本上插入失败的原因都是,网站上有多个链接对应同一篇文章,因此重复插入会导致失败。

var filename = source_name + "_" + (new Date()).toFormat("YYYY-MM-DD") +
  "_" + fetch.title + ".json";
var filepath = 'people-result/'+filename

if (strtitle != ''){
  const  mysql=require('mysql')
  const db=mysql.createPool({host:'localhost',port:'3306',user:'root',password:'123456',database:'crawler_data'});
  str=`'`+fetch.source_encoding+`'`+','+`'`+fetch.title+`'`+','+`'`+fetch.source_name+`'`+','+`'`+fetch.publish_date+`'`+','+`'`+fetch.keywords+`'`+','+`'`+fetch.desc+`'`+','+`'`+fetch.content+`'`
  querystr='INSERT INTO news1 (source_encoding,title,author,publish_date,keywords,description,content) VALUE('+str+');'
  //console.log(querystr)
  db.query(querystr,function(err,data){
      if(err)
      {
          var errorname = source_name + "_" + (new Date()).toFormat("YYYY-MM-DD") +"_" + fetch.title + ".json";
          var errorpath = 'people-result/error/'+filename
          fs.writeFileSync(errorpath, JSON.stringify(querystr));
      }else{
          fs.writeFileSync(filepath, JSON.stringify(fetch));
      }

  })        

第二部分:网站部分

1.根据自己的数据库配置

let connection = mysql.createConnection({
	host:'localhost',  
	port:3306,	
	user:'root',  
	password:'xxxxxx', 
	database:'crawler_data'  
});
connection.connect();

2.搜索并跳转显示结果

搜索框效果如下

跳转后结果如下,这里只截取了搜索结果的前五条:

3.搜索框的代码实现

index.html

<html>
<body>
<form action="http://127.0.0.1:8081/process_get" method="GET">
	<h1>输入单词并搜索:</h1>
 <input type="text" name="keyword">  
<input type="submit" value="搜索">
</form>
</body>
</html>

4.搜索结果的显示-代码

先从数据库里搜索,再逐条在网页上显示
js文件,运行时通过cmd里node加文件名

app.get('/process_get', function (req, res) {
   var response = {
       "search":req.query.keyword,
   };
   var searchword = req.query.keyword
   console.log(user_sql)
   var user_sql = "SELECT * FROM news WHERE title like '%" + searchword + "%' Order By publish_date desc;";
   console.log(user_sql)
   connection.query(user_sql,function(err,result){
      if(err){
     console.log('[query]-:'+err);
     res.send("没有搜索到结果")
      }else{
         result = "<h1>搜索结果为:</h1>"
         for (var i=0;i<result.length;i++)
         {result += "<p>"
          result += result[i].title
         result += " "
         result += result[i].publish_date
         result += "</p>"
         }
         res.send(result)
      }
  })
}) 

5.时间热度分析效果

从数据库中统计每天包括该关键词的新闻数量时间热度分析
sql:

var user_sql = "SELECT publish_date,count(*) as Num FROM news WHERE title like '%" + searchword + "%' group by publish_date order by publish_date desc;"

第三部分:总结

爬虫总是有各种各样的意外情况,插入数据库也是,特别是引号的问题!!
因此在写爬虫代码的过程中需要加入很多判断,去除undefined和null的情况,还有很多异常处理,否则就会没爬几条就因为各种各样的原因异常退出
新闻网站相对来说没遇到什么反爬虫机制,爬取起来还是比较方便的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值