robots.txt文件的解析及过滤

news/2024/7/3 0:31:20

什么是robots.txt文件?

        robots.txt(统一小写)是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的漫游器(又称网络蜘蛛),此网站中的哪些内容是不能被搜索引擎的漫游器获取的,哪些是可以被(漫游器)获取的。 因为一些系统中的URL是大小写敏感的,所以robots.txt的文件名应统一为小写。robots.txt应放置于网站的根目录下。如果想单独定义搜索引擎的漫游器访问子目录时的行为,那么可以将自定的设置合并到根目录下的robots.txt,或者使用robots元数据。Robots.txt协议并不是一个规范,而只是约定俗成的,所以并不能保证网站的隐私。 ——维基百科(http://zh.wikipedia.org/wiki/Robots.txt)

基本属性:

User-agent: 定义搜索引擎的类型
Disallow: 定义禁止搜索引擎收录的地址
Allow: 定义允许搜索引擎收录的地址
Crawl-delay:支持Crawl-delay参数,设置为多少秒,以等待同服务器之间连续请求(网络爬虫的礼貌策略)
#:一些robots.txt 会有注释,#后面都是注释内容,需要过滤掉 

一些例子;

User-agent: * 这里的*代表的所有的搜索引擎种类,*是一个通配符
Disallow: /admin/ 这里定义是禁止爬寻admin目录下面的目录
Disallow: /require/ 这里定义是禁止爬寻require目录下面的目录
Disallow: /ABC/ 这里定义是禁止爬寻ABC目录下面的目录
Disallow: /cgi-bin/*.htm 禁止访问/cgi-bin/目录下的所有以".htm"为后缀的URL(包含子目录)。
Disallow: /*?* 禁止访问网站中所有的动态页面
Disallow: /jpg$ 禁止抓取网页所有的.jpg格式的图片
Disallow:/ab/adc.html 禁止爬去ab文件夹下面的adc.html文件。
Allow: /cgi-bin/ 这里定义是允许爬寻cgi-bin目录下面的目录
Allow: /tmp 这里定义是允许爬寻tmp的整个目录
Allow: .htm$ 仅允许访问以".htm"为后缀的URL。
Allow: .gif$ 允许抓取网页和gif格式图片
Crawl-delay: 10 

C++实现解析robots.txt,并对url进行过滤:

robotsFilter.h

/*
* urlFilter.h
*
* Created on: 2012-3-26
* Author: xiaojay
*/
#ifndef URLFILTER_H_
#define URLFILTER_H_
#include "../urlFrontier/url.h"
#include<string.h>
#include<assert.h>
#include <iostream>
using namespace std;
#define MAXDISALLOW 100

//接口
class urlFilter
{
public:
// 当u合法时,返回true,否则返回false
virtual bool filter(url * u) = 0;
virtual bool filter(const char * url_text) = 0;
};
//robots.txt过滤
class robotsFilter : public urlFilter
{
public:
robotsFilter(const char * host_name , const char * robots_txt);
~robotsFilter();
virtual bool filter(url * u);
virtual bool filter(const char * url_text);
void parseRobots();
void printDisallow();
bool robotsMatch(char * match , char * file);
private:
char * strlwr(char *); //辅助函数,大写转小写
char * disallow [MAXDISALLOW];
int disallow_size;
char * allow[MAXDISALLOW];
int allow_size;
char * hostname;
char * robotstxt;
int crawldelay ;
};

#endif /* URLFILTER_H_ */

robotsFilter.cpp

/*
* robotFilter.cpp
*
* Created on: Mar 31, 2012
* Author: mayday
*/
#include "urlFilter.h"

// 初始化相关参数
robotsFilter::robotsFilter(const char * host_name , const char * robots_txt)
{
assert(host_name!=NULL && robots_txt!=NULL);
int len = strlen(host_name);
hostname = new char [len + 1];
strcpy(hostname,host_name);

len = strlen(robots_txt);
robotstxt = new char [len + 1];
strcpy(robotstxt,robots_txt);

disallow_size = 0;
allow_size = 0;
crawldelay = 0;
}
robotsFilter::~robotsFilter()
{
delete [] hostname;
delete [] robotstxt;
for(int i=0;i<disallow_size;i++)
{
delete [] disallow[i];
}
for(int i=0;i<allow_size;i++)
{
delete [] allow[i];
}
}

char* robotsFilter::strlwr( char* str )
{
char* orig = str;
// process the string
for (;*str != '\0'; str++ )
*str = tolower(*str);
return orig;
}
//解析robots文本
void robotsFilter::parseRobots()
{
//cout<<robotstxt<<endl;
//key:value
char key [32];
char value [100];
int i,j;
int posl = 0, posm = 0 ,posr =0;
int len = strlen(robotstxt);
bool hasAgent = false;
//总体思路,确定三个标志的位置,然后分割字符串. ——>posl( key )posm( value )posr
while(posl<len && posm<len && posr<len)
{
//找到第一个不为空格和换行符的字符位置,确定posl
while(posl<len && (robotstxt[posl]==' '
|| robotstxt[posl]=='\n' || robotstxt[posl]=='\r')) posl++;
//以#开头的,直接过滤掉该行
if(robotstxt[posl]=='#')
{
while(posl<len && robotstxt[posl]!='\n') posl++;
continue;
}
//找‘:’,确定posm
posm = posl+1;
while(posm<len && robotstxt[posm]!=':') posm++;
//找换行符位置,确定posr
posr = posm+1;
while(posr<len && robotstxt[posr]!='\n') posr++;

for(j=0,i=posl;i<posm;i++)
{
if(robotstxt[i]!=' '&&robotstxt[i]!='\t'&&robotstxt[i]!='\r'&&robotstxt[i]!='\n')
key[j++] = robotstxt[i];
}
key[j] = '\0';
for(j=0,i=posm+1;i<posr;i++)
{
if(robotstxt[i]!=' '&&robotstxt[i]!='\t'&&robotstxt[i]!='\r'&&robotstxt[i]!='\n')
value[j++] = robotstxt[i];
}
value[j]='\0';
posl = posr;
//cout<<key<<"\t"<<value<<endl;
//确定user-agent,是否针对本爬虫
if(strcmp(strlwr(key),"user-agent")==0){
if(strcmp(value,"*")==0||strcmp(value,"webcrawler")==0)
{
hasAgent = true;
}
else hasAgent = false;
}
if(hasAgent)
{
int len_val = strlen(value);
if(len_val<=0) continue;
if(strcmp(strlwr(key),"disallow")==0 && disallow_size<MAXDISALLOW)
{
disallow[disallow_size] = new char [len_val+1];
strcpy(disallow[disallow_size],strlwr(value));
disallow_size++;
}
else if (strcmp(strlwr(key),"allow")==0 && allow_size<MAXDISALLOW)
{
allow[allow_size] = new char [len_val+1];
strcpy(allow[allow_size],strlwr(value));
allow_size++;
}
else if(strcmp(strlwr(key),"craw-delay")==0)
{
crawldelay = 0;
int len_val = strlen(value);
for(int i=0;i<len_val;i++)
{
crawldelay = crawldelay * 10 + value[i]-'0';
}
}
}
}
}

void robotsFilter::printDisallow()
{
for(int i=0;i<disallow_size;i++)
{
cout<<disallow[i]<<endl;
}
}
//url->file属性与robots.txt匹配串的匹配,如果匹配成功返回true,否则返回false
bool robotsFilter::robotsMatch(char * match ,char * file)
{
int len_match = strlen(match);
if(len_match<=1) return true;
int len_file = strlen(file);
if(len_match>len_file) return false;
// ends with '$'
if(match[len_match-1]=='$')
{
int pos_match = 0;
char head [50],tail[20];
pos_match = len_match - 1;
while(pos_match>=0&&match[pos_match]!='*') pos_match --;
strncpy(head,match,pos_match);
head[pos_match] = '\0';
strncpy(tail,match+pos_match+1,len_match-pos_match-2);
tail[len_match-pos_match-2] = '\0';
int lhead = pos_match;
int ltail = len_match-pos_match-2;
int i = 0;
while(i<lhead && head[i]==file[i]) i++;
if(i!=lhead) return false;
i=0;
while(i<ltail && tail[i]==file[len_file-ltail+i]) i++;
if(i!=ltail) return false;
return true;
}
// 统计 '*'
int starlist [10] , starcount=0;
for(int i=0;i<len_match;i++)
if(match[i]=='*')
starlist[starcount++] = i;
//if have no star
if(starcount==0)
{
int i=0;
while(i<len_match && match[i]==file[i]) i++;
if(i!=len_match) return false;
else return true;
}
// if have star
/*
算法如下,首先按照'*',分割为多给子串
然后各个子串需按序匹配到file文本,且每个子串按首次匹配为准
*/
int i=0;
//test head
while(i<starlist[0]&&match[i]==file[i]) i++;
if (i!=starlist[0]) return false;
//test tail
if(match[len_match-1]!='*')
{
int length = len_match - (starlist[starcount-1] + 1);
i = 0;
while(i<length && match[len_match - i -1] == file[len_file - i -1]) i++;
if (i!=length) return false;
}

// match each star
int start_match , end_match , start_file = starlist[0];
char case_str [50];
for(int i=1;i<starcount;i++)
{
start_match = starlist[i-1]+1;
end_match = starlist[i];
strncpy(case_str,match+start_match,end_match-start_match);
case_str[end_match-start_match] = '\0';
int i = start_file;
int j = 0;
//match case_str , perhaps KMP algorithms is better than mine
while(i<len_file && j<(end_match-start_match))
{
if(file[i]==case_str[j]){
++i;++j;
}else{
i = i-j+1;
j = 0;
}
}
if(j==(end_match-start_match))
{
start_file = i;
}else return false;
}
return true;
}

// if u->file matches robots.txt ,return false ; otherwise true
bool robotsFilter::filter(url * u)
{
/*
*robots.txt里面可能有Allow,也可能有Disallow
*其实如果两个都设置的话,会有一点歧义,crawler不知道到底应不应该爬
*这里给出的方法是:两个都进行测试,只要通过一个就ok。
*/
if(disallow_size<=0 && allow_size<=0 ) return true;
bool pass_disallow = true;
if(disallow_size>0)
{
if(strcmp(disallow[0],"/")==0 || strcmp(disallow[0],"*")==0
||strcmp(disallow[0]," ")==0 ||strcmp(disallow[0],"")==0)
pass_disallow = false;
else
{
for(int i=0;i<disallow_size;i++)
{
if (robotsMatch(disallow[i],u->getFile())) {
pass_disallow = false;
break;
}
}
}
}
else pass_disallow = false;
if(pass_disallow==true) return true;

bool pass_allow = false;
if (allow_size>0)
{
if(strcmp(allow[0],"/")==0 || strcmp(allow[0],"*")==0) pass_allow = true;
else
{
for(int i=0;i<allow_size;i++)
{
if (robotsMatch(allow[i],u->getFile()))
{
pass_allow = true;
break;
}
}
}
}
return pass_allow;
}
bool robotsFilter::filter(const char * url_text)
{
char tmp [150];
strcpy(tmp,url_text);
url * u = new url(tmp,0,0);
bool res = filter(u);
delete u;
return res;
}





http://lihuaxi.xjx100.cn/news/252674.html

相关文章

微信推出自研NLP大规模语言模型WeLM,现已开放API推动应用落地

大规模语言模型领域迎来新“选手”。近日&#xff0c;微信AI推出自研NLP大规模语言模型WeLM &#xff0c;该模型是一个尺寸合理的中文模型&#xff0c;能够在零样本以及少样本的情境下完成包多语言任务在内的多种NLP任务。 同时&#xff0c;微信AI团队也提供了WeLM的体验网页和…

TOPSIS算法及代码

TOPSIS的全称是“逼近于理想值的排序方法” 根据多项指标、对多个方案进行比较选择的分析方法&#xff0c;这种方法的中心思想在于首先确定各项指标的正理想值和负理想值&#xff0c;所谓正理想值是一设想的最好值&#xff08;方案&#xff09;&#xff0c;它的的各个属性值都…

Spring Boot thymeleaf模版支持,css,js等静态文件添加

Thymeleaf引入 Thymeleaf是一个Java模板引擎开发库&#xff0c;可以处理和生成HTML、XML、JavaScript、CSS和文本&#xff0c;在Web和非Web环境下都可以正常工作。 1.添加依赖包 <dependency><groupId>org.springframework.boot</groupId><artifactId>…

CSS布局之-水平垂直居中

对一个元素水平垂直居中&#xff0c;在我们的工作中是会经常遇到的&#xff0c;也是CSS布局中很重要的一部分&#xff0c;本文就来讲讲CSS水平垂直居中的一些方法。另外&#xff0c;文中的css都是用less书写的&#xff0c;如果看不懂less&#xff0c;可以把我给的demo链接打开&…

【Spring】编程式事务的应用场景理解

前言 我们经常在使用Spring全家桶开发JavaEE项目的时候&#xff0c;一想到事务就会习惯性的使用声明式注解Transactional,由Spring框架帮你做AOP实现事务的回滚&#xff0c;但是声明式事务恰恰比较方便&#xff0c;所以有些场景下并不好用&#xff0c;接下来我来举一个例子&am…

【青少年编程(第26周)】一下子多了很多事!

2021年08月15日&#xff08;周日&#xff09;晚20:00我们在青少年编程竞赛交流群开展了第二十六次直播活动。我们直播活动的主要内容如下&#xff1a; 首先&#xff0c;我们奖励了上周测试超过60分的小朋友。 其次&#xff0c;介绍了Datawhale青少年组队学习活动的规划&#x…

ranlib

ranlib 产生archive文件的索引 The index lists each symbol defined by a member of an archive that is a relocatable object file.

【MATLAB】数组运算

&#xff08;这里这列举笔者不熟悉的&#xff0c;容易忘的数组运算&#xff09; 1、数组的转置 >> a[1 2 3 4 5 6 7]a 1 2 3 4 5 6 7>> bab 1234567 2、对数组的赋值 >> a([1 4])[0 0]a 0 2 3 0 5 6 73、注…