CSpider
c语言实现的易用的高效的网络爬虫框架:)。
安装与使用方法:
确认你的电脑中,已经安装下面的库:
curl
libuv
libxml2
pcre
liburi
进入core文件夹,编译文件,命令如下:
make
接着要配置动态库,将.so文件和.h文件移动到相应的位置,命令如下:
make install
这时,就可以开始编译你写好的文件(例如 test.c),命令如下:
gcc -o test test.c -lcspider -I /usr/include/libxml2
其中,-lcspider将链接我们上述编译完成的cspider动态链接库,而-I /usr/include/libxml2则是让编译器能够找到libxml2库的头文件,当然你最好使用Makefile文件。
API
初始化设置
cspider_t *init_cspider()
在程序一开始的时候,获取到cspider_t变量。是必不可少的函数。
void cs_setopt_url(cspider_t , char )
为cspider_t设置程序启动时要抓取的url,在第二个参数传入url字符串即可,url字符串可以不用包含http://或htpps://。可以多次调用,即可插入多个url任务。
void cs_setopt_cookie(cspider_t , char )
第二个参数设置cookie,格式为var1=abc; var2=qwe。可选项。
void cs_setopt_useragent(cspider_t , char )
第二个参数设置user agent,可选项。
void cs_setopt_proxy(cspider_t , char )
第二个参数设置代理的地址,可选项。
void cs_setopt_timeout(cspider_t *, long)
设置超时时间,单位为毫秒,可选项。
void cs_setopt_logfile(cspider_t , FILE )
设置输出日志的打印文件,可选项。不设置,则不会输出日志。
void cs_setopt_process(cspider_t , void (*process)(cspider_t , char*, char , void ), void *)
设置解析函数process,解析函数process的第二个参数为抓取到的完整的数据字符串,第三个参数url为当前抓取的url,第四个参数void*指向用户自定义的上下文信息。该上下文指针通过cs_setopt_process的第三个参数来设置。
void cs_setopt_save(cspider_t , void (*save)(void, void*), void*)
设置数据持久化函数save,save的参数中第一个指针指向解析函数传入的信息,第二个指针指向用户自定义的上下文信息。该上下文指针同样通过cs_setopt_save的第三个参数来设置。
void cs_setopt_threadnum(cspider_t *cspider, int , int )
设置线程的数量,其中,第二个参数,可以传入DOWNLOAD与SAVE,分别表示,将要设置下载线程的数量,或是解析与保存线程的数量。第三个参数为要设置的线程的数量。可选项,默认的线程数量均为5个。
int cs_run(cspider_t *)
启动cspider的函数,在程序的最后调用。
自定义函数部分
void saveString(cspider_t , void , int)
在自定义的解析函数中,可以调用此函数。数据持久化,将字符串传入自定义的数据持久化函数。其中,当第三个参数为LOCK时,会保证数据持久化时是线程安全的。反之,NO_LOCK也是如此。
void saveStrings(cspider_t , void *, int, int)
需要存储多组数据时使用,第三个参数为数据的个数。第四个参数可为LOCK或NO_LOCK,用法同上。
void addUrl(cspider_t *cspider, char *url)
在自定义的解析函数中,调用此函数。可以将解析获取到的url,再次加入任务队列。
void addUrls(cspider_t *cspider, char **urls, int size)
将size个url,再次加入任务队列。
void freeString(char*)
回收动态分配的字符串空间,可在regexAll和xpath之后使用,用于回收获取到的字符串。
void freeStrings(char **, int)
回收动态分配的字符串数组,第二个参数表示数组中字符串的个数。可在regexAll和xpath之后使用,用于字符串回收。
解析工具API
正则表达式:
int regexAll(const char *regex, char *str, char **res, int num, int flag);
regex : 正则匹配的规则
str : 待匹配的字符串
res : 用来保存返回的字符串的数组
num : res数组的大小
flag : 可为REGEX_ALL和REGEX_NO_ALL,输出全部,或者只是匹配的部分。
返回获取的字符串的个数
int match(char *regex, char *str);
是否匹配。返回1表示成功,返回0标示失败。
xpath解析html和xml
int xpath(char *xml, char *path, char **get, int num);
xml : 待匹配的字符串
path : xpath规则
get : 保存返回字符串的数组
num : get数组的大小
返回获取的字符串的个数
解析json
cspider里集成了cJSON库,可以非常方便地解析json。具体的使用方法,请看这里。
上述regexAll和xpath中获取的字符串数组,建议使用freeStrings函数进行回收。
使用例子
输出优酷电影页面,第一页的所有电影名称。
#include
void p(cspider_t *cspider, char *d, char *url, void *user_data) {
char *get[100];
int size = xpath(d, "//div[@id='listofficial']/div[@class='yk-row yk-v-80']/div[@class='yk-col3']/div[@class='p p-small']/div[@class='p-meta pa']/div[@class='p-meta-title']/a/@title", get, 100);
int i;
saveStrings(cspider, (void**)get, size, LOCK);
freeStrings(get, size);
}
void s(void *str, void *user_data) {
char *get = (char *)str;
FILE *file = (FILE*)user_data;
fprintf(file, "%s\n", get);
return;
}
int main() {
cspider_t *spider = init_cspider();
char *agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:42.0) Gecko/20100101 Firefox/42.0";
cs_setopt_url(spider, "http://www.youku.com/v_olist/c_96_s_0_d_0_g_0_a_0_r_0_u_0_pt_0_av_0_ag_0_sg_0_mt_0_lg_0_q_0_pr_0_h_0_p_1.html");
cs_setopt_useragent(spider, agent);
//指向自定义的解析函数,和数据持久化函数
cs_setopt_process(spider, p, NULL);
cs_setopt_save(spider, s, stdout);
//设置抓取线程数量,和数据持久化的线程数量
cs_setopt_threadnum(spider, DOWNLOAD, 2);
cs_setopt_threadnum(spider, SAVE, 2);
return cs_run(spider);
}