作者:gzshun. 原创作品,转载请标明出处!
来源:http://blog.csdn.net/gzshun
唐僧:你想要啊?悟空,你要是想要的话你就说话嘛,你不说我怎么知道你想要呢,虽然你很有诚意地看着我,可是你还是要跟我说你想要的。你真的想要吗?那你就拿去吧!你不是真的想要吧?难道你真的想要吗?……
悟空:我Kao!
唐僧:喂喂喂!大家不要生气,生气会犯了嗔戒的!悟空你也太调皮了,我跟你说过叫你不要乱扔东西,你怎么又…你看我还没说完你又把棍子给扔掉了!月光宝盒是宝物,你把他扔掉会污染花草草也是不对的!
三.下载个人博客的主页,并分析出必要的信息,比如下载:http://blog.csdn.net/gzshun主页,程序将该文件保存到了本地的"index.html"文件中,先贴出一点html文件的源码,这样就更加清晰的了解代码的字符串解析:
博客的总页数:
博客的排名,积分信息:
贴出源码,这几个字符串解析函数没必要看,自己看下html的规则就能解析出来了:
以上使用了rank_info_addr数组,是为了在while (fgets(line, sizeof(line), fp)) 循环里面方便赋值。
博客里面可能有很多页,必须我的博客就有2页,这时候网址是这样:
http://blog.csdn.net/gzshun/article/list/1
http://blog.csdn.net/gzshun/article/list/2
所以循环下载blog.csdn.net对应自己的博客列表就行,网页文件的名称如:/gzshun/article/list/1 把gzshun改为自己的csdn的id就是了。
来源:http://blog.csdn.net/gzshun
唐僧:你想要啊?悟空,你要是想要的话你就说话嘛,你不说我怎么知道你想要呢,虽然你很有诚意地看着我,可是你还是要跟我说你想要的。你真的想要吗?那你就拿去吧!你不是真的想要吧?难道你真的想要吗?……
悟空:我Kao!
在开篇,先happy下,有个好心情,才能天天向上,奋发图强,自强不息。
继《自己动手编写CSDN博客备份工具-blogspider》与《自己动手编写CSDN博客备份工具-blogspider之源码分析(1)》博文后,继续贴出处理的一些函数,原理很简单。
一.在博客的下载过程中,打印了一些信息到屏幕,也保存到了*.log文件
/*********************************************************
将爬虫链表的内容打印到log文件,格式为"csdn_id.log",比如
我的博客的地址为: "gzshun.log"
*********************************************************/
static void print_spider(blog_spider *spider_head)
{
char file[BUFSIZE] = {0};
char tmpbuf[BUFSIZE] = {0};
blog_spider *spider;
FILE *fp;
sprintf(file, "%s.log", csdn_id);
fp = fopen(file, "a+");
if (NULL == fp) {
#ifdef SPIDER_DEBUG
fprintf(stderr, "fopen: %s\n", strerror(errno));
#endif
return;
}
setvbuf(fp, NULL, _IONBF, 0);
fseek(fp, 0, SEEK_END);
spider = spider_head->next;
while (spider) {
fprintf(fp, "%d:\n"
"%-15s : %s\n"
"%-15s : %s\n"
"%-15s : %s\n"
"%-15s : %d\n"
"%-15s : %d\n"
"%-15s : %s\n\n",
spider->blog->b_seq_num,
"title", spider->blog->b_title,
"url", spider->blog->b_url,
"date", spider->blog->b_date,
"reads", spider->blog->b_reads,
"comments", spider->blog->b_comments,
"download",
(spider->blog->b_download == BLOG_DOWNLOAD) ? "Download" : "UnDownload");
spider = spider->next;
}
fclose(fp);
}
/*********************************************************
将博客的基本信息打印到标准输出
*********************************************************/
static void print_rank(blog_rank *rank)
{
char file[BUFSIZE] = {0};
FILE *fp;
sprintf(file, "%s.log", csdn_id);
fp = fopen(file, "w+");
if (NULL == fp) {
#ifdef SPIDER_DEBUG
fprintf(stderr, "fopen: %s\n", strerror(errno));
#endif
return;
}
setvbuf(stdout, NULL, _IONBF, 0);
fprintf(stdout, "CSDN ID : %s\n"
"TITLE : %s\n"
"URL : %s/%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n",
csdn_id,
rank->b_title,
CSDN_BLOG_URL,
csdn_id,
rank->b_page_view,
rank->b_integral,
rank->b_ranking,
rank->b_original,
rank->b_reship,
rank->b_translation,
rank->b_comments);
fprintf(fp, "CSDN ID : %s\n"
"TITLE : %s\n"
"URL : %s/%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n",
csdn_id,
rank->b_title,
CSDN_BLOG_URL,
csdn_id,
rank->b_page_view,
rank->b_integral,
rank->b_ranking,
rank->b_original,
rank->b_reship,
rank->b_translation,
rank->b_comments);
fclose(fp);
}
唐僧:喂喂喂!大家不要生气,生气会犯了嗔戒的!悟空你也太调皮了,我跟你说过叫你不要乱扔东西,你怎么又…你看我还没说完你又把棍子给扔掉了!月光宝盒是宝物,你把他扔掉会污染花草草也是不对的!
二.申请了空间,在程序结束后必须释放,要不内存泄露了,污染到内存,污染到花花草草也是不对的.
/*********************************************************
释放爬虫链表的空间
*********************************************************/
static void free_spider(blog_spider * spider_head)
{
blog_spider *pspider;
blog_spider *tmp;
pspider = spider_head;
while (pspider) {
if (pspider->blog->b_url) {
free(pspider->blog->b_url);
}
if (pspider->blog->b_host) {
free(pspider->blog->b_host);
}
if (pspider->blog->b_page_file) {
free(pspider->blog->b_page_file);
}
if (pspider->blog->b_local_file) {
free(pspider->blog->b_local_file);
}
if (pspider->blog->b_title) {
free(pspider->blog->b_title);
}
if (pspider->blog->b_date) {
free(pspider->blog->b_date);
}
free(pspider->blog);
tmp = pspider->next; /*保存下一个节点地址*/
free(pspider);
pspider = tmp;
}
}
/*********************************************************
释放博客基本信息结构体空间
*********************************************************/
static void free_rank(blog_rank *rank)
{
if (rank->b_title) {
free(rank->b_title);
}
if (rank->b_page_view) {
free(rank->b_page_view);
}
if (rank->b_integral) {
free(rank->b_integral);
}
if (rank->b_ranking) {
free(rank->b_ranking);
}
if (rank->b_original) {
free(rank->b_original);
}
if (rank->b_reship) {
free(rank->b_reship);
}
if (rank->b_translation) {
free(rank->b_translation);
}
if (rank->b_comments) {
free(rank->b_comments);
}
free(rank);
}
三.下载个人博客的主页,并分析出必要的信息,比如下载:http://blog.csdn.net/gzshun主页,程序将该文件保存到了本地的"index.html"文件中,先贴出一点html文件的源码,这样就更加清晰的了解代码的字符串解析:
博客标题:
<div class="header">
<div id="blog_title">
<h1>
<a href="/gzshun">Open Linux C/C++专栏</a></h1>
<h2></h2>
<div class="clear">
</div>
</div>
博客的总页数:
<!--显示分页-->
<div id="papelist" class="pagelist">
<span> 35条数据 共2页</span><strong>1</strong> <a href="/gzshun/article/list/2">2</a> <a href="/gzshun/article/list/2">下一页</a> <a href="/gzshun/article/list/2">尾页</a>
只需要获取到"尾页"前面的数字即可.
博客的排名,积分信息:
<span>gzshun</span>
</div>
<div id="blog_medal">
</div>
<ul id="blog_rank">
<li>访问:<span>54524次</span></li>
<li>积分:<span>1070分</span></li>
<li>排名:<span>第5615名</span></li>
</ul>
<ul id="blog_statistics">
<li>原创:<span>29篇</span></li>
<li>转载:<span>6篇</span></li>
<li>译文:<span>0篇</span></li>
<li>评论:<span>209条</span></li>
</ul>
贴出源码,这几个字符串解析函数没必要看,自己看下html的规则就能解析出来了:
/**********************************************************
获取博客的基本信息,包括以下几点(以下是按照页面的顺序,
若不按照该顺序,每次查找必须重设偏移量到开头rewind(fp)):
这里获取很多信息, 具体参考blog_spider与blog_rank结构体
**********************************************************/
static int get_blog_info(blog_spider * spider_head, blog_rank * rank)
{
FILE *fp;
int count;
char *posA, *posB, *posC, *posD, *posE;
char tmpbuf[BUFSIZE] = {0};
char tmpbuf2[BUFSIZE] = {0};
char line[BUFSIZE] = {0};
char *rank_info_addr[7];
fp = fopen(spider_head->blog->b_local_file, "r");
if (NULL == fp) {
fprintf(stderr, "fopen: %s\n", strerror(errno));
return -1;
}
/*查找博客的标题*/
sprintf(tmpbuf, "<a href=\"/%s\">", csdn_id);
while (fgets(line, sizeof(line), fp)) {
posA = strstr(line, tmpbuf);
if (posA) {
posA += strlen(tmpbuf);
posB = strstr(posA, "</a>");
*posB = 0;
/*设置爬虫头结点的标题*/
spider_head->blog->b_title = strdup(posA);
rank->b_title = strdup(posA);
#ifdef SPIDER_DEBUG
printf("%s\n", spider_head->blog->b_title);
#endif
break;
}
}
/*查找博客文章的总页数*/
while (fgets(line, sizeof(line), fp)) {
posA = strstr(line, HTML_MULPAGE);
if (posA) {
fgets(line, sizeof(line), fp);
posB = strrstr(line, BLOG_HREF);
/* /gzshun/article/list/N, N就是总页数 */
memset(tmpbuf, 0, sizeof(tmpbuf));
sprintf(tmpbuf, "/%s/%s/", csdn_id, BLOG_NEXT_LIST);
posB += strlen(BLOG_HREF) + strlen(tmpbuf);
posC = strchr(posB, '"');
*posC = 0;
rank->b_page_total = atoi(posB);
spider_head->blog->b_seq_num = rank->b_page_total;
#ifdef SPIDER_DEBUG
printf("b_page_total = %d\n", rank->b_page_total);
#endif
break;
}
}
/*总共有7条信息: 访问 积分 排名 原创 转载 译文 评论*/
while (fgets(line, sizeof(line), fp)) {
posA = strstr(line, BLOG_RANK);
if (posA) {
count = 0;
while (fgets(line, sizeof(line), fp)) {
posB = strstr(line, BLOG_LI);
if (posB) {
if (7 == count) {
break;
}
posB += strlen(BLOG_LI);
posC = strstr(posB, BLOG_SPAN_HEAD);
posD = posC + strlen(BLOG_SPAN_HEAD);
posE = strstr(posD, BLOG_SPAN_END);
*posC = 0;
*posE = 0;
memset(tmpbuf, 0, sizeof(tmpbuf));
memset(tmpbuf2, 0, sizeof(tmpbuf2));
strcpy(tmpbuf, posB);
strcpy(tmpbuf2, posD);
strcat(tmpbuf, tmpbuf2);
rank_info_addr[count++] = strdup(tmpbuf);
}
}
rank->b_page_view = rank_info_addr[0];
rank->b_integral = rank_info_addr[1];
rank->b_ranking = rank_info_addr[2];
rank->b_original = rank_info_addr[3];
rank->b_reship = rank_info_addr[4];
rank->b_translation = rank_info_addr[5];
rank->b_comments = rank_info_addr[6];
break;
}
}
fclose(fp);
return 0;
}
以上使用了rank_info_addr数组,是为了在while (fgets(line, sizeof(line), fp)) 循环里面方便赋值。
博客里面可能有很多页,必须我的博客就有2页,这时候网址是这样:
http://blog.csdn.net/gzshun/article/list/1
http://blog.csdn.net/gzshun/article/list/2
所以循环下载blog.csdn.net对应自己的博客列表就行,网页文件的名称如:/gzshun/article/list/1 把gzshun改为自己的csdn的id就是了。
先来杯咖啡,待下一篇文章,前几天奔波在火车上,辛苦啊,今天及时赶到,马上发表,持之以恒。。