记得3个月前,同样在csdn的博客上洋洋洒洒写了有几千字的文章,一个错点满满心血顷刻付之东流,后再也提不起写文章的兴趣了。
这些日子在捉摸着在自己的站上实现抓取网络文章收集后以供己用, 道德不道德的暂且不论。 君不见世面上大数据行业多火爆,其内容不也是采集各方数据么?
实现蜘蛛,对于前端来说,肯定使用自家专长语言 nodejs了。数据存储方面定了mongodb,不为别的,就为存取数据格式自由。
第一章节:安装mongodb
工欲善其事必先利其器,当然我们应首先搭建nodejs环境和安装mongodb了。 其中安装mongodb费了大半周折。 再次善意提醒各位新手,切莫尽信书的照mongodb官网上使用yum安装,国内的yum源根本就没有官网上最新的3.2*版本,最简单的方法就是直接下载编译后的源码包。地址:https://www.mongodb.com/download-center#community,下载完包后,解压缩。 解压后,mv 至 /usr/local/lib/下。然后建立服务启动命令软链至mongodb服务所在位置:
sudo ln -s /usr/local/lib/mongodb/bin/mongod /usr/local/bin/mongod
sudo ln -s /usr/local/lib/mongodb/bin/mongo /usr/local/bin/mongo
mongdb数据存储服务分为mongod服务端和mongo 客户端shell命令服务。建立软链后,我们可以开始启动mongod服务端的程序了,类同其它工具的工程化思维,一般软件都有一个配置项决定此软件的属性和设置,bin目录下的mongodb.conf,设置了mongodb的日志存放、数据存储、数据读取。。。等的相关配置。
需要注意的是网上所搜索到的大部分配置类似于 js声明方式的配置项是针对于 2.4*版本的。如:
#port=27027
#MongoDB数据文件目录
dbpath=/usr/local/mongodb/data
#MongoDB日志文件目录
logpath=/usr/local/mongodb/log/mongo.log
#日志文件自动累加
logappend=true
从2.6*版本开始,mongodb的配置采用了全新的yaml文件格式,参考官网说明:
File Format
IMPORTANT:Changed in version 2.6: MongoDB 2.6 introduces a YAML-based configuration file format. The 2.4 configuration file
YAML does not support tab characters for indention: use spaces instead.
systemLog:
destination: file
#指定是一个文件
path: "/var/log/mongodb/"
#日志存放位置
logAppend: true
#产生日志内容追加到文件
processManagement:
fork: true
#以守护进程的方式运行MongoDB,创建服务器进程
pidFilePath: "/var/run/mongodb/mongodb.pid"
#pid文件路径
net:
bindIp: 127.0.0.1
#绑定ip地址访问mongodb,多个ip逗号分隔
port: 27017
#端口
maxIncomingConnections: 65536
#默认65536,mongodb实例接受的最多连接数,如果高于操作系统接受的最大线程数,设置无效。
# http:
# enabled: true
#http端口最好关闭
#RESTInterfaceEnabled: false
#即使http接口选项关闭,如果这个选项打开后会有更多的不安全因素
storage:
dbPath: "/data/db"
#数据文件存放路径
engine: "wiredTiger"
#数据引擎
mmapv1:
smallFiles: true
nsSize: 16
quota:
maxFilesPerDB: 8
wiredTiger:
engineConfig:
#wt引擎配置
cacheSizeGB: 1
#看服务器情况来进行设置
directoryForIndexes: true
#索引是否按数据库名进行单独存储
collectionConfig:
blockCompressor: zlib
#压缩配置
indexConfig:
prefixCompression: true
#索引配置
journal:
enabled: true
#记录操作日志,防止数据丢失。
directoryPerDB: true
#指定存储每个数据库文件到单独的数据目录。如果在一个已存在的系统使用该选项,需要事先把存在的数据文件移动到目录。
operationProfiling:
#slowOpThresholdMs: 100
#指定慢查询时间,单位毫秒,如果打开功能,则向system.profile集合写入数据
mode: "slowOp"
#off、slowOp、all,分别对应关闭,仅打开慢查询,记录所有操作。
security:
#keyFile: "/data/mongodb-keyfile"
#指定分片集或副本集成员之间身份验证的key文件存储位置
#clusterAuthMode: "keyFile"
#集群认证模式,默认是keyFile
authorization: "disabled"
#访问数据库和进行操作的用户角色认证
#默认为磁盘的5%,指定oplog的最大尺寸。对于已经建立过oplog.rs的数据库,指定无效
mongod服务启动有两种方式,一种是启动时加载配置文件,另一种时启动时指定配置。
第二章节:mongo服务与mongodb的数据库概念
MongoDB shell version: 3.2.7
connecting to: test
Server has startup warnings:
2016-07-28T15:30:49.189+0800 I CONTROL [initandlisten]
2016-07-28T15:30:49.189+0800 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. The locked memory size is 32768 bytes, it should be at least 65536 bytes
> show dbs //查看数据库列表
local 0.000GB
mydb 0.000GB
mydb1 0.000GB
mydb2 0.000GB
node-mongo-examples 0.000GB
test 0.000GB
> use mydb1 //进入mydb1数据库,并启用当前数据库操作权限,所以后续的操作就是在mydb1下的操作
switched to db mydb1
> show collections //查看当前数据库的数据集合
movies
> db.movies.find() //查看当前数据集合的数据
{ "_id" : ObjectId("57982cf5f40fb6d87061e865"), "ahref" : "", "__v" : 0 }
{ "_id" : ObjectId("57982dda620543107367b88b"), "ahref" : "", "__v" : 0 }
>
mongodb数据库的存贮形式和概念与我们所熟悉的mysql是有些区别的,
下表将帮助您更容易理解Mongo中的一些概念:
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
通过下图实例,我们也可以更直观的的了解Mongo中的一些概念:
此节参考:http://www.runoob.com/mongodb/mongodb-tutorial.html
第三章节:蜘蛛程序与mongodb存储
for(var i = 1; i <= pageNum; i++){
pageUrls.push('http://www.**.com/post/?page='+i)
}
var http = require('http'),
superagent = require('superagent'),
cheerio = require('cheerio'),
mongoose = require('mongoose'),
mongourl = 'mongodb://localhost/mydb2',
pageUrls = [],
pageNum = 15;
for(var i = 1; i <= pageNum; i++){
pageUrls.push('http://www.75team.com/post/?page='+i)
}
mongoose.connect(mongourl);
var Schema = mongoose.Schema;
//骨架模版
var movieSchema = new Schema({
ahref : String
})
//模型
var Movie = mongoose.model('Movie', movieSchema);
//存储数据
pageUrls.forEach(function(pageUrl){
superagent.get(pageUrl)
.end(function(err,page){
var $ = cheerio.load(page.text);
var quoteUrls = $('.entry-content blockquote a');
for(var i = 0;i < quoteUrls.length; i++){
var articalUrl ='{ahref:"'+ quoteUrls.eq(i).attr("href") +'"},';
var moive = new Movie({
ahref : articalUrl
})
//保存数据库
moive.save(function(err) {
if (err) {
console.log('保存失败')
return;
}
console.log('meow');
})
}
})
})
第四章节:爬取后response或fs写入
var http = require('http'),
url = require('url'),
superagent = require('superagent'),
cheerio = require('cheerio'),
articalUrls = [],
pageUrls = [],
pageNum = 15;
for(var i = 1; i <= pageNum; i++){
pageUrls.push('http://www.***.com/post/?page='+i)
}
function onRequest(req,res){
res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});
pageUrls.forEach(function(pageUrl,j){
superagent.get(pageUrl)
.end(function(err,page){
var $ = cheerio.load(page.text);
var quoteUrls = $('.entry-content blockquote a');
for(var i = 0;i < quoteUrls.length; i++){
var articalUrl = quoteUrls.eq(i).attr('href');
articalUrls.push(articalUrl);
}
if(j == 14){
res.write('<img src="http://img.zcool.cn/community/01013d56ebaea86ac7257d204ec3c8.gif"/><br/>请等待,数据汇总中');
setTimeout(function(){
res.end(JSON.stringify(articalUrls));
},5000)
}
})
})
}
http.createServer(onRequest).listen(3000);
var http = require('http'),
fs = require('fs'),
superagent = require('superagent'),
cheerio = require('cheerio'),
dbtxt = '/home/xiaoang/git/web/site/static/data/article1.txt',
pageUrls = [],
pageNum = 15;
for(var i = 1; i <= pageNum; i++){
pageUrls.push('http://www.***.com/post/?page='+i)
}
pageUrls.forEach(function(pageUrl,j){
superagent.get(pageUrl)
.end(function(err,page){
var $ = cheerio.load(page.text);
var quoteUrls = $('.entry-content blockquote a');
for(var i = 0;i < quoteUrls.length; i++){
var articalUrl ='{ahref:"'+ quoteUrls.eq(i).attr("href") +'"},';
fs.writeFile(dbtxt, articalUrl,{'flag':'a'}, function (err) {
if (err) throw err;
})
}
if(j == 14)
console.log('It\'s saved!');
})
})
/*fs.readFile(dbtxt, 'utf-8', function(err, data) {
if (err) {
throw err;
}
console.log(data);
});*/