您的位置:首页 > 其它

自己动手编写CSDN博客备份工具-blogspider

2012-02-01 18:15 477 查看
作者:gzshun. 原创作品,转载请标明出处!

来源:http://blog.csdn.net/gzshun

网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁,自动索引,模拟程序或者蠕虫。

网络爬虫最重要的任务,就是从互联网搜索出需要的信息,将网页抓取下来并分析,很多搜索引擎,比如百度,谷歌,后台都有一只很强悍的网络爬虫,用来访问互联网上的网页,图片,视频等内容,并建立索引数据库,使用户能在百度搜索引擎中搜索到您网站的网页、图片、视频等内容。

我们常见的几个大型搜索引擎公司的爬虫名称:

1.谷歌(Google) -> Googlebot

2.百度(Baidu)爬虫名称:Baiduspider

3.雅虎(Yahoo) -> Yahoo! Slurp

4.有道(Yodao) -> YodaoBot

5.搜狗(sogou) -> Sogou spider

6.MSN -> msmbot

7.腾讯搜搜 -> Sosospider

最近我突然想自己动手写一只小型的博客爬虫,将自己在CSDN博客网站写的文章给抓取下来,想做个博客备份工具。当了解到网络爬虫的用途后,就来动手实现一个应用,用来备份自己在CSDN的博客,这样即使没有网络,或者文章丢失了,我手头都有一个备份。记得上次在微博看过CSDN创始人蒋涛先生说的一句话,他想做一个CSDN博客生成PDF文档的工具,其实那也相当于对自己博客的备份,这样就能很方便的浏览自己的写的文章。

我写的这个"blogspider"程序,将会把自己博客信息提取出来,并将所有的文章下载到本地。这里只是简单的下载网页而已,里面的图片我没有下载,那得涉及到太多的东西。如果电脑有网络,将会很容易的看到博客里面的图片,如果没有网络,图片将无法显示。

blogspider程序由C语言编写的,基于Linux平台,我编写该程序的环境如下:

[plain] view
plaincopy

gzshun@ubuntu:~$ uname -a

Linux ubuntu 2.6.32-24-generic-pae #39-Ubuntu SMP Wed Jul 28 07:39:26 UTC 2010 i686 GNU/Linux

gzshun@ubuntu:~$ gcc -v

Using built-in specs.

Target: i486-linux-gnu

Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu

Thread model: posix

gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)

本人在putty终端测试程序,可以正确的显示中文,要设置为UTF-8,或者GB2312,如果显示乱码,切换一下字符集试试。

一.blogspider的功能简介:



1.获取博客的基本信息:

博客标题

博客访问量

博客积分

博客排名

博客原创文章数量

博客转载文章数量

博客译文文章数量

博客评论数量

2.下载博客到本地:

博客主题

博客发表日期

博客阅读次数

博客评论次数

二.blogspider涉及到的知识点:

1.文件I/O

2.网络编程socket

3.数据结构-链表

4.内存分配

三.blogspider程序执行流程:

以我的博客为例:

1.将"http://blog.csdn.net/gzshun"主页下载到本地

2.分析该主页,获取到博客的URL

3.将博客的URL添加到爬虫链表

4.遍历爬虫链表,将博客下载到本地

5.将下载日志保存在gzshun.log

四.blogspider程序的重要部分:

1.爬虫链表的结构体

[cpp] view
plaincopy

typedef struct tag_blog_info {

char *b_url; /*网址*/

char *b_host; /*网站服务器主机名*/

char *b_page_file; /*页面文件名称*/

char *b_local_file; /*本地保存的文件名称*/

char *b_title; /*博客主题*/

char *b_date; /*博客发表日期*/

int b_port; /*网址端口号*/

int b_sockfd; /*网络套接字*/

int b_reads; /*阅读次数*/

int b_comments; /*评论次数*/

int b_download; /*下载状态*/

int b_lock; /*处理锁*/

int b_seq_num; /*序号*/

}blog_info;



typedef struct tag_blog_spider {

blog_info *blog;

struct tag_blog_spider *next;

}blog_spider;

2.博客基本信息结构体

[cpp] view
plaincopy

typedef struct tag_blog_rank {

int b_page_total; /*博客总页数*/

char *b_title; /*博客标题*/

char *b_page_view; /*博客访问量*/

char *b_integral; /*博客积分*/

char *b_ranking; /*博客排名*/

char *b_original; /*博客原创文章数量*/

char *b_reship; /*博客转载文章数量*/

char *b_translation; /*博客译文文章数量*/

char *b_comments; /*博客评论数量*/

}blog_rank;

3.定义的函数

[cpp] view
plaincopy

static char *strrstr(const char *s1, const char *s2);

static char *strfchr(char *s);

static int init_spider(blog_spider **spider);

static int init_rank(blog_rank **rank);

static void insert_spider(blog_spider *spider_head, blog_spider *spider);

static int spider_size(blog_spider *spider_head);

static void print_spider(blog_spider *spider_head);

static void print_rank(blog_rank *rank);

static void free_spider(blog_spider *spider_head);

static void free_rank(blog_rank *rank);

static int get_blog_info(blog_spider *spider_head, blog_rank *rank);

static int analyse_index(blog_spider *spider_head);

static int download_index(blog_spider *spider_head);

static int download_blog(blog_spider *spider);

static int get_web_host(const char *hostname);

static int connect_web(const blog_spider *spider);

static int send_request(const blog_spider * spider);

static int recv_response(const blog_spider * spider);

4.strrstr是自己实现的,C库没有提供

1.strrstr函数:从一个字符串中查找指定字符串,返回最后一次出现的地址

程序如下:

[cpp] view
plaincopy

/**************************************************************

strrstr : 查找指定字符串, 返回最后一次出现的地址, 自己实现

***************************************************************/

static char *strrstr(const char *s1, const char *s2)

{

int len2;

char *ps1;



if (!(len2 = strlen(s2))) {

return (char *)s1;

}



ps1 = (char *)s1 + strlen(s1) - 1;

ps1 = ps1 - len2 + 1;



while (ps1 >= s1) {

if ((*ps1 == *s2) && (strncmp(ps1, s2, len2) == 0)) {

return (char *)ps1;

}

ps1--;

}



return NULL;

}

5.初始化爬虫链表

[cpp] view
plaincopy

/*********************************************************

初始化博客爬虫的链表节点, 申请空间并赋空值

*********************************************************/

static int init_spider(blog_spider * * spider)

{

*spider = (blog_spider *)malloc(sizeof(blog_spider));

if (NULL == *spider) {

#ifdef SPIDER_DEBUG

fprintf(stderr, "malloc: %s\n", strerror(errno));

#endif

return -1;

}



(*spider)->blog = (blog_info *)malloc(sizeof(blog_info));

if (NULL == (*spider)->blog) {

#ifdef SPIDER_DEBUG

fprintf(stderr, "malloc: %s\n", strerror(errno));

#endif

free(*spider);

return -1;

}



(*spider)->blog->b_url = NULL;

(*spider)->blog->b_host = strdup(CSDN_BLOG_HOST);

(*spider)->blog->b_page_file = NULL;

(*spider)->blog->b_local_file = NULL;

(*spider)->blog->b_title = NULL;

(*spider)->blog->b_date = NULL;

(*spider)->blog->b_port = CSDN_BLOG_PORT;

(*spider)->blog->b_sockfd = 0;

(*spider)->blog->b_reads = 0;

(*spider)->blog->b_comments = 0;

(*spider)->blog->b_download = BLOG_UNDOWNLOAD;

(*spider)->blog->b_lock = BLOG_UNLOCK;

(*spider)->blog->b_seq_num = 0;



(*spider)->next = NULL;



return 0;

}

6.初始化博客基本信息结构体

[cpp] view
plaincopy

/*********************************************************

初始化博客基本信息结构体,包含以下几个变量:

1.博客页面总页数

2.博客标题

3.博客访问量

4.博客积分

5.博客排名

6.博客原创文章数量

7.博客转载文章数量

8.博客译文文章数量

9.博客评论数量

*********************************************************/

static int init_rank(blog_rank **rank)

{

*rank = (blog_rank *)malloc(sizeof(blog_rank));

if (NULL == *rank) {

#ifdef SPIDER_DEBUG

fprintf(stderr, "malloc: %s\n", strerror(errno));

#endif

return -1;

}



(*rank)->b_page_total = 0;

(*rank)->b_title = NULL;

(*rank)->b_page_view = NULL;

(*rank)->b_integral = NULL;

(*rank)->b_ranking = NULL;

(*rank)->b_original = NULL;

(*rank)->b_reship = NULL;

(*rank)->b_translation = NULL;

(*rank)->b_comments = NULL;



return 0;

}

五.blogspider遇到的问题:

1.博客标题如果有'/','?',或者其他不规则的符号,文件将会创建失败。

解决方案:将不规则的符号赋空,并在后面连接"xxx"字符串,表示省略;

2.在接受网站服务器响应的时候,要将select函数的时间设置长点,有时候因为网络差的问题,将会超时导致退出程序。在blogspider里面,将timeout设置30s。

3.本程序在考虑加入多线程遍历爬虫链表,经过尝试,连接网站服务器会出现竞争问题,将导致连接延时,影响程序效率,暂时不考虑。

六.blogspider运行截图:





使用blogspider:

这里以下载我的博客为例,我CSDN的ID是:gzshun, 网址是:http://blog.csdn.net/gzshun





title : 博客标题

url : 博客网址

date : 博客发表日期

reads : 博客阅读次数

comments : 博客评论次数

download : 博客下载状态



以下这张图片是在windows查看的,通过samba连接到ubuntu服务器。我博客上面的所有文章已经成功地下载到本地。



打开下载在本地的html文件,此时有网络。



打开下载在本地的html文件,此时无网络。



若需要blogspider的源程序,请留下您的E-mail(注意要写成我后面的那种形式,否则会被非法网络爬虫抓取),或者直接联系我的E-mail:gzshuns#163.com (#->@).
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: