一只简单的网络爬虫(基于linux C/C++)————配置文件设计及读取
来源:互联网 发布:两小无猜 网络剧 编辑:程序博客网 时间:2024/05/21 06:13
一般来说linux下比较大型的程序都是以配置文件作为参数介质传递的,该爬虫也采用配置文件的方式来获取参数,配置文件格式大致如下:
max_job_num=1#seeds=https://www.baidu.com#seeds=http://bbs.scut.edu.cn/classic/logfile=spiderq.log
以“=”作为分割符,左边为key,右边为valve,主要包含的参数内容为:最大的任务数,种子,日志文件,日志等级,深度,模块路径,支持的文件类型,等,以“#”开头的就作为注释。
配置文件结构体如下:
Config * initconfig(){ Config *conf = (Config *)malloc(sizeof(Config)); conf->max_job_num = 10; conf->seeds = NULL; conf->include_prefixes = NULL; conf->exclude_prefixes = NULL; conf->logfile = NULL; conf->log_level = 0; conf->max_depth = INF; conf->make_hostdir = 0; conf->module_path = NULL; conf->stat_interval = 0; //conf->modules return conf;}
是一个全局的结构体,若以类的方式实现则可以设计成单例类,里面的参数主要保存从配置文件中读取到的东西。加载配置文件后,配置文件的参数设置被保存到了Config结构体的,供后面的函数使用
加载配置文件的函数如下:
void loadconfig(Config *conf){ FILE *fp = NULL; char buf[MAX_CONF_LEN+1]; int argc = 0; char **argv = NULL; int linenum = 0; char *line = NULL; const char *err = NULL; if ((fp = fopen(CONF_FILE, "r")) == NULL) //打开配置文件 { SPIDER_LOG(SPIDER_LEVEL_ERROR, "Can't load conf_file %s", CONF_FILE); } while (fgets(buf, MAX_CONF_LEN+1, fp) != NULL)//获取一行到buf { linenum++; line = strim(buf);//去除空格,在qstring中 //过滤# if (line[0] == '#' || line[0] == '\0') continue; //count: 分割后的字符串长度 //limit: 分割多少次 argv = strsplit(line, '=', &argc, 1); if (argc == 2) { if (strcasecmp(argv[0], "max_job_num") == 0) { conf->max_job_num = atoi(argv[1]); } //extern char *strdup(char *s);//功 能: 将串拷贝到新建的位置处//strdup()在内部调用了malloc()为变量分配内存,//不需要使用返回的字符串时,需要用free()释放相应的内存空间,//否则会造成内存泄漏 //strcasecmp(忽略大小写比较字符串) else if (strcasecmp(argv[0], "logfile") == 0) { conf->logfile = strdup(argv[1]); } else if (strcasecmp(argv[0], "include_prefixes") == 0) { conf->include_prefixes = strdup(argv[1]); } else if (strcasecmp(argv[0], "exclude_prefixes") == 0) { conf->exclude_prefixes = strdup(argv[1]); } else if (strcasecmp(argv[0], "seeds") == 0) { conf->seeds = strdup(argv[1]); } else if (strcasecmp(argv[0], "module_path") == 0) { conf->module_path = strdup(argv[1]); } else if (strcasecmp(argv[0], "load_module") == 0) { conf->modules.push_back(strdup(argv[1])); } else if (strcasecmp(argv[0], "log_level") == 0) { conf->log_level = atoi(argv[1]); } else if (strcasecmp(argv[0], "max_depth") == 0) { conf->max_depth = atoi(argv[1]); } else if (strcasecmp(argv[0], "stat_interval") == 0) { conf->stat_interval = atoi(argv[1]); } else if (strcasecmp(argv[0], "make_hostdir") == 0) { conf->make_hostdir = yesnotoi(argv[1]); } else if (strcasecmp(argv[0], "accept_types") == 0) { conf->accept_types.push_back(strdup(argv[1])); } else { err = "Unknown directive"; goto conferr; } } else { err = "directive must be 'key=value'"; goto conferr; } } return;conferr: SPIDER_LOG(SPIDER_LEVEL_ERROR, "Bad directive in %s[line:%d] %s", CONF_FILE, linenum, err); }
下面介绍几个函数:
(1)fgets函数是用来获取行的,该函数可读取文件中的一行,并且会包含换行符
(2)strim函数用于去除空格,其实现如下:参数是行指针
//去除空格char * strim(char *str){ char *end, *sp, *ep; size_t len; sp = str; end = ep = str+strlen(str)-1; //从行首开始 while(sp <= end && isspace(*sp)) sp++; //从行尾开始 while(ep >= sp && isspace(*ep)) ep--; //计算长度 len = (ep < sp) ? 0 : (ep-sp)+1; sp[len] = '\0'; return sp;}
(3)strsplit函数用于分割字符串,实现方法如下:
//切割字符串,函数内申请,函数外释放//count: 分割后的字符串长度//limit: 分割多少次char ** strsplit(char *line, char delimeter, int *count, int limit){ char *ptr = NULL, *str = line; char **vector = NULL; *count = 0; //strchr函数原型:extern char *strchr(const char *s,char c);查找字符串s中首次出现字符c的位置。 while((ptr = strchr(str, delimeter))) { *ptr = '\0'; vector = (char **)realloc(vector,((*count)+1)*sizeof(char *)); vector[*count] = strim(str);//等号前面部分去除空格后放入vector str = ptr+1;//此时str指向等号后面部分(会继续查找后面的等号) (*count)++; if (--limit == 0) break; } if (*str != '\0') { vector = (char **)realloc(vector,((*count)+1)*sizeof(char *)); vector[*count] = strim(str);//分割空格 (*count)++; } return vector;}
(4)strcasecmp函数是忽略大小写比较字符串,该函数用来比较配置文件的key值
定义函数 int strcasecmp (const char *s1, const char *s2);
函数说明 strcasecmp()用来比较参数s1和s2字符串,比较时会自动忽略大小写的差异。
返回值 若参数s1和s2字符串相等则返回0。s1大于s2则返回大于0 的值,s1 小于s2 则返回小于0的值。
(5)strdup函数
extern char *strdup(char *s);
功 能: 将串拷贝到新建的位置处,strdup()在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏
- 一只简单的网络爬虫(基于linux C/C++)————配置文件设计及读取
- 一只简单的网络爬虫(基于linux C/C++)————读取命令行参数及日志宏设计
- 一只简单的网络爬虫(基于linux C/C++)————socket相关及HTTP
- 一只简单的网络爬虫(基于linux C/C++)————开篇
- 一只简单的网络爬虫(基于linux C/C++)————守护进程
- 一只简单的网络爬虫(基于linux C/C++)————支持动态模块加载
- 一只简单的网络爬虫(基于linux C/C++)————线程相关
- 一只简单的网络爬虫(基于linux C/C++)————利用正则表达式解析页面
- 一只简单的网络爬虫(基于linux C/C++)————主事件流程
- 一只简单的网络爬虫(基于linux C/C++)————浅谈并发(IO复用)模型
- 一只简单的网络爬虫(基于linux C/C++)————Url处理以及使用libevent进行DNS解析
- Linux企业级项目实践之网络爬虫(3)——设计自己的网络爬虫
- python网络爬虫入门(一)——简单的博客爬虫
- c/c++: 读取配置文件(文本)内容的简单实现
- Linux C语言程序设计(二十)——基于Linux C的简单web服务器
- linux c读取配置文件
- linux c 读取配置文件
- 基于人人网的简单爬虫(一)——正则表达式
- 从xcode7回到6.4之后的(null): Linker command failed with exit code 1 (use -v to see invocation)问题
- Unity5.2.0无法使用Visual Studio 2013调试问题解决方案
- MQ安装
- 黑马程序员——Java基础---集合
- tf卡恢复工具
- 一只简单的网络爬虫(基于linux C/C++)————配置文件设计及读取
- Working with Apple’s App Transport Security
- Masonry介绍与使用实践(快速上手Autolayout)
- Web前端工程师之布局设计
- 万能的pdf转换成jpg转换器软件
- linux signal 处理
- 错误:Access restriction: The type 'OperatingSystemMXBean' is not API (restriction on required library
- Linux下CoreSeek的安装测试【官方】
- Solr IV——Solr查询