百科词条爬虫 一、爬取的关键要素 每个词条的词条名、词条描述、词条链接。 二、爬取词条,如何存储? 1、cname标签,description标签,url标签, 爬取以后使用这种格式存储,方便我们使用,可以用正则表达式匹配出我们需要的内容。 2、词条数据存储格式
<cname>词条名</cname>
<description>词条描述</description>
<url>词条链接</url>
三、词条爬虫的工作模式 1、种子URL (Original URL) 爬虫的工作起点,处理的第一条链接,种子URL是精心挑选包含更多链接数据的URL(指向网页的链接)。
2、一般的爬虫里面都会有两个容器 u_container:该容器存储未下载的,未解析的URL。 p_container:存储已下载,已解析的URL。
我们的种子URL是不可以直接放到u_container中的,因为爬虫中有很重要的一环就是去重,因为这个A词条点击以后里面比如包含了BCD三个其他的词条我们点击C词条进入它的页面,这里面也有可能又包含了BD词条,否则就会造成大量的重复下载。
3、去重模块 将URL输入到去重模块,去重模块先到p_container中检测该URL是否存在,再到u_container中检测,都不存在,将该URL添加到u_container中。
4、进入下载以后,(下载模块不再赘述)得到词条的网页源码,然后对网页源码进行解析,得到我们需要的内容。
解析流程:解析器(正则技术:匹配提取关键数据) 1)内容解析:词条名、词条描述、词条链接,save模块保存,注意存储格式。 2)链接解析:爬虫是需要拓扑的,从一个网页链接中解析中它有的新的链接。 URL(O_URL)->去重( p_container+u_container)->下载(网页源码)->解析(内容解析+链接解析)->URL(N_URL)->去重->下载->解析->URL-> … … 我们需要对链接解析进行控制,因为每次解析都会产生很多新的链接,u_container和p_container之间严重的使用不平衡,如果一直解析,u_container分分钟就会爆满。而下载相对较慢,所以我们对链接解析进行限制,如果u_container中未解析的URL数量到达了某个数量,那么就不再进行链接解析(内容是一直要解析的),等数量降下来再继续。
typedef struct
{
url_t *node_queue;
int front;
int rear;
int max;
int cur;
}container_t;
container_t *spider_container_create(int);
int spider_container_setnode(container_t* , url_t);
int spider_container_getnode(container_t* ,url_t*);
int spider_remove_duplication(container_t* ,container_t* ,const char *);
int spider_analytical_html(url_t*, container_t* ,container_t* );
int spider_url_controler(const char *);
四、解析模块代码
#include<SPIDER.h>
int spider_analytical_html(url_t* node, container_t* u_ct, container_t* p_ct)
{
int fd = open(node->save_file,O_RDONLY);
int fsize = lseek(fd,0,SEEK_END);
char *pstring = mmap(NULL ,fsize ,PROT_READ ,MAP_PRIVATE ,fd ,0);
char *jstr = pstring;
url_t rnode;
const char *h1_pst = "<h1 >\\([^<]\\+\\?\\)</h1>";
const char *des_pst = "<meta name=\"description\" content=\"\\([^\"]\\+\\?\\)\">";
const char *a_pst = "<a[^>]\\+\\?href=\"\\(/item/[^\"]\\+\\?\\)\"[^>]\\+\\?>[^<]\\+\\?</a>";
regex_t h_reg,d_reg,a_reg;
int cnum = 2;
regmatch_t h_ma[cnum];
regmatch_t d_ma[cnum];
regmatch_t a_ma[cnum];
char h1[1024];
char url[4096];
char desc[4096];
bzero(h1,1024);
bzero(url,4096);
bzero(desc,4096);
regcomp(&h_reg,h1_pst,0);
regcomp(&d_reg,des_pst,0);
regcomp(&a_reg,a_pst,0);
if((regexec(&h_reg,pstring,cnum,h_ma,0)) == 0)
snprintf(h1,h_ma[1].rm_eo - h_ma[1].rm_so +1,"%s",pstring +h_ma[1].rm_so);
if((regexec(&d_reg,pstring,cnum,d_ma,0)) == 0){
snprintf(desc,d_ma[1].rm_eo - d_ma[1].rm_so +1,"%s",pstring +d_ma[1].rm_so);
}
if(u_ct->cur < 100){
while((regexec(&a_reg,pstring,cnum,a_ma,0)) == 0){
snprintf(url,a_ma[1].rm_eo -a_ma[1].rm_so + 24,"https://baike.baidu.com%s",pstring+a_ma[1].rm_so);
if(u_ct->cur != u_ct->max){
if(!spider_remove_duplication(u_ct,p_ct,url)){
strcpy(rnode.alpha_url,url);
spider_container_setnode(u_ct,rnode);
}
bzero(url,sizeof(url));
pstring+=a_ma[0].rm_eo;
unlink(node->save_file);
}else
break;
}
}
printf("Analytical_Html TITLE[%s]\n",h1);
printf("Analytical_Html DESCRIPTION[%s]\n",desc);
printf("Analytical_Html This URL [%s]\n",node->alpha_url);
regfree(&h_reg);
regfree(&d_reg);
regfree(&a_reg);
munmap(jstr,fsize);
close(fd);
return 0;
}
完整代码链接:https://github.com/Birdbird-66/BirdBird-A.git
运行部分截图
|