赞
踩
本学期期中作业是 新闻爬虫及爬取结果的查询网站,作为只有c语言基础的小菜鸟,刚看到要求时还是一脸懵,通过半个学期的学习,借助老师的代码,撸起袖子加油干,跌跌撞撞地也实现了爬虫。先来看看啥是爬虫,爬虫就是个自动获取网络内容的程序,又称为网页蜘蛛,网络机器人......(来自百度百科...)ok 话不多说 现在开始实现新闻爬虫以及爬取结果的查询网站。
1.Nodejs
百度搜索nodejs进入官网
点击下载,找到自己需要的版本
按照提示一路next 安装完成 在cmd中输入node -v可以查看安装版本
2.编码工具VsCode
这里因为以前写C/C++时下载过VScode所以稍微下个插件直接用了,也可以下载WebStorm,Sublime等等
WebStorm下载地址: WebStorm: The Smartest JavaScript IDE, by JetBrains
Sublime下载地址: Sublime Text - Text Editing, Done Right
VScode是一个轻量且强大的跨平台开源代码编辑器(IDE) 打开VScode应用商店下载nodejs插件
3.安装MySQL
下载地址:MySQL :: Download MySQL Community Server
数据库 根据自己需要的版本 下载 后面会详细描述
要下载的工具下载的差不多了,下面正式开始爬虫
这里先看一下npm这个东西
npm就是Nodejs下的包管理器
但是,npm的服务器位于国外可能会影响安装 所以淘宝团队做了国内镜像cnpm,与官方同步频率目前为 10分钟 一次以保证尽量与官方服务同步。
安装方法:
npm install cnpm -g --registry=https://registry.npm.taobao.org
cnpm -v
来测试是否成功安装通过改变地址来使用淘宝镜像
https://registry.npmjs.org/
npm config get registry
查看npm的仓库地址npm config set registry https://registry.npm.taobao.org
来改变默认下载地址,达到可以不安装cnpm
就能采用淘宝镜像的目的,然后使用上面的get命令查看是否成功。搞定之后 就可以用cnpm来下载需要的包
之后可以根据需要引入不同的包,在npm网站可以对包的用法进行查询
比如
获取网页内容(http\request\superagent等)
筛选网页信息(cheerio)
输出或存储信息(console\fs\mongodb\mysql等)
下面简单介绍几个
- var request = require('request');
-
- // 通过 GET 请求来读取 http://cnodejs.org/ 的内容
- request('https://nba.hupu.com/', function (error, response, body) {
- if (!error && response.statusCode == 200) {
- // 输出网页内容
- console.log(body);
- }
- });
运行之后得到
利用chrome 右键 查看网页源代码 发现和上面是一样的
用来实现将数据存储到数据库中
- var mysql = require("mysql");
- var pool = mysql.createPool({
- host: '127.0.0.1',
- user: 'root',
- password: 'root',//密码
- database: 'crawl'
- });
后面会详细介绍
cheerio是nodejs为服务器特别定制的,快速、灵活、实施的jQuery核心实现。适合各种Web爬虫程序。
借用老师发的代码来爬一篇北京大学官网的文章
- var myRequest = require('request')
- var myCheerio = require('cheerio')
- var myURL = 'https://www.pku.edu.cn/about.html'
- 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代码
- 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');
首先安装所需要的包
当发现提示throw err; ^ Error: Cannot find module 'xxxx'时
说明并没有安装xxxx这个包
在命令行输入cnpm install xxxx 回车就可以下载所需要的包
- var source_name = "中国新闻网";
- var myEncoding = "utf-8";
- var seedURL = 'http://www.chinanews.com/';
要爬取的网站 以及查看的此网站编码是utf-8 以及正则表达式。。
正则表达式是第一次接触到的概念,其实就是一种被用来检索、替换那些符合某个模式(规则)的文本
这里附上学习链接 正则表达式 – 语法 | 菜鸟教程
- 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}日)/
这里是爬取的信息 关键词 作者 日期等
-
- 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 爬下来的内容以浏览网址形式储存
- 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) };
-
- seedurl_news.each(function(i, e) { //遍历种子页面里所有的a链接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); //读取新闻页面
- });
- });

如果要爬取新闻内容的话 就必须读取种子页面 思路是解析种子页面的所有 a href 链接并遍历——规整化链接,符合新闻url的正则表达式的就爬取
- function newsGet(myURL) { //读取新闻页面
- request(myURL, function(err, res, body) { //读取新闻页面
- //try {
- var html_news = myIconv.decode(body, myEncoding); //用iconv转换编码
- //console.log(html_news);
- var $ = myCheerio.load(html_news, { decodeEntities: true });
- myhtml = html_news;
- //} catch (e) { console.log('读新闻页面并转码出错:' + e);};
-
- console.log("转码读取成功:" + myURL);
- 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();

构建json对象准备写入文件并且建立一个空fetch以存储数据 这样可以将爬到的数据存储到构建的json文件中
- 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('年', '-')
- 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", ""); //摘要

需要爬取的内容标题 日期 作者 内容 来源 以及摘要
- ar filename = source_name + "_" + (new Date()).toFormat("YYYY-MM-DD") +
- "_" + myURL.substr(myURL.lastIndexOf('/') + 1) + ".json";
- 存储json
- fs.writeFileSync(filename, JSON.stringify(fetch));
最后 将爬取的内容储存到fetch中并建立文件
到这里基本完成一个可以爬取新闻网页内容,并且存储的爬虫,下面来运行看结果
文件夹中出现很多的json文件 用记事本打开看一下内容
得到了想到得到的内容 还不错
第一次使用mysql,这也是我走最多弯路的地方,在官网安装完成后
完成一系列配置工作 可以参照MySQL 安装 | 菜鸟教程
可以在我的电脑——管理——服务中找到MySQL
在此过程中我也遇到很多问题:
比如 进行配置时一定要以管理员身份运行。
第一次登陆后会要求强制修改密码,好好记住自己的密码......
还有这种低级的...mysql写成mysqld......
记住实在不行就重启 net stop mysql 和net start mysql
ok 当你克服了种种困难终于进入了你的数据库
因为要将数据存入数据库中,所以对刚才的代码进行修改
首先将存入json文件部分注释掉
-
- var mysql = require('./mysql.js');
加入所需要的模块
- var mysql = require("mysql");
- var pool = mysql.createPool({
- host: '127.0.0.1',
- user: 'root',
- password: 'root',//密码
- database: 'crawl'
- });
- var query = function(sql, sqlparam, callback) {
- pool.getConnection(function(err, conn) {
- if (err) {
- callback(err, null, null);
- } else {
- conn.query(sql, sqlparam, function(qerr, vals, fields) {
- conn.release(); //释放连接
- callback(qerr, vals, fields); //事件驱动回调
- });
- }
- });
- };
- var query_noparam = function(sql, callback) {
- pool.getConnection(function(err, conn) {
- if (err) {
- callback(err, null, null);
- } else {
- conn.query(sql, function(qerr, vals, fields) {
- conn.release(); //释放连接
- callback(qerr, vals, fields); //事件驱动回调
- });
- }
- });
- };
- exports.query = query;
- exports.query_noparam = query_noparam;

mysql.js文件 其中数据库的用户名是root 密码为root 使用database名为crawl 当然这些东西可以自己设置
比如进入数据库后在命令提示符中使用create database xxx创建名为xxx的database 使用use xxx使用名为xxx的database等等操作......
当然这里我还是根据老师的来操作了
- var fetchAddSql = 'INSERT INTO fetches(url,source_name,source_encoding,title,' +
- 'keywords,author,publish_date,crawltime,content) VALUES(?,?,?,?,?,?,?,?,?)';
- var fetchAddSql_Params = [fetch.url, fetch.source_name, fetch.source_encoding,
- fetch.title, fetch.keywords, fetch.author, 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);
- }
实现将内容写入到数据库中
代码修改完成后进去数据库,借用老师的fetches代码,创建表格
创建完成后 运行程序
进入数据库中 输入select url , title from fetches;(注意结尾要有分号)可以看到
爬取的内存存储到了数据库的表格中(这里可以下载navicat等数据库管理软件,嫌麻烦我并没有下....想要更加直观对数据库进行可视化可以尝试)
到这里就实现了将新闻网页内容进行爬取,并且存入数据库中。
创建一个html文件,以实现输入要查询title而输出包含查询内容的新闻
- <!DOCTYPE html>
- <html>
-
- <body>
- <form action="http://127.0.0.1:8080/process_get" method="GET">
- <br> 标题:<input type="text" name="title">
- <input type="submit" value="Submit">
- </form>
- <script>
- </script>
- </body>
-
- </html>
js代码如下:
- var express = require('express');
- var mysql = require('./mysql.js')
- var app = express();
- //app.use(express.static('public'));
- app.get('/7.03.html', function(req, res) {
- res.sendFile(__dirname + "/" + "7.03.html");
- })
- app.get('/7.04.html', function(req, res) {
- res.sendFile(__dirname + "/" + "7.04.html");
- })
- app.get('/process_get', function(req, res) {
- res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' }); //设置res编码为utf-8
- //sql字符串和参数
- var fetchSql = "select url,source_name,title,author,publish_date from fetches where title like '%" +
- req.query.title + "%'";
- mysql.query(fetchSql, function(err, result, fields) {
- console.log(result);
- res.end(JSON.stringify(result));
- });
- })
- var server = app.listen(8080, function() {
- console.log("访问地址为 http://127.0.0.1:8080/7.03.html")
-
- })

code runner运行之后:
在浏览器中打开网址后
在标题中输入要查询的内容,例如“赵立坚”
就可以看到含有“赵立坚”的新闻内容
在完成了老师的代码例子之后,开始自己寻找可以爬取的新闻网站进行爬虫操作,以及存入数据库
但是要注意对网站源代码进行分析 进行代码修改
爬取结束之后 打开数据库看一下
从另一个网站爬取了很多新闻 一共有了150条 数据库中多了很多内容 ok搞定
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。