对 没错 嗯 用C语言写的爬虫
首先,既然是爬虫,当然要能够访问网页,用C访问网页的方法也有很多,这里选择的是一种相对比较方便的wininet
,用InternetOpenUrl
打开url然后读取数据就可以了
于是定义了一个获取网页源码的函数,ASSERT
是个人习惯问题,见最后的完整代码
int GetUrl(char *url, char *buf, int *length){
long unsigned int readDataLength;
HINTERNET hinternet=InternetOpen(0,INTERNET_OPEN_TYPE_PRECONFIG,0,0,0);
ASSERT(!hinternet,InternetCloseHandle(hinternet));
HINTERNET hinternetopen=InternetOpenUrl(hinternet,url,0,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
ASSERT(!hinternetopen,InternetCloseHandle(hinternet);InternetCloseHandle(hinternetopen));
*length=0;
do{
InternetReadFile(hinternetopen,buf+*length,1024,&readDataLength);
*length+=readDataLength;
}while(readDataLength);
return 1;
}
然后通过api获取数据之后的提取信息,如何分析api不是本文的内容不详细讨论,api接口如下:
#define API_URL "https://www.duitang.com/napi/blog/list/by_album/?album_id=%d&limit=24&start=%d"
提取信息就不要想着用regex
了,C的正则库用过几个感觉都不怎么好用,甚至感觉不如自己写for循环,于是
void Parse(char *buf,int *now,int total,char *dest){
char result[1024],name[1024];
char *p,*q;
for(p=buf;*p;p++){
if(!strncmp(p,"path",4)){
p+=12;
strcpy(result,"http");
for(q=result+4;*p!='"';p++,q++){
*q=*p;
}
*q=0;
//puts(result);
GetFileName(result,name,dest);
GetFile(result,name);
printf("[%4d/%4d] %s\n",++*now,total,name);
}
}
}
思路就是找到每一项的path
然后复制url,下面的获取文件数和获取文件名比较简单不多说了
int GetFileCount(char *buf,int *next){
char *p;
int total=0;
if(p=strstr(buf,"total")){
total=atoi(p+7);
p=strstr(buf+7,"next_start");
*next=atoi(p+12);
}
return total;
}
int GetFileName(char *name,char *buf,char *dest){
char *last,*p,*q=buf;
if(dest[1]==':'){
p=dest;
while(*q++=*p++);
if(*(q-2)!='/'&&*(q-2)!='\\'){
*(q-1)='/';
}
}
for(p=name;*p;p++){
if(*p=='/')
last=p;
}
last++;
while(*q++=*last++);
//puts(buf);
return 1;
}
然后是下载文件的问题,因为文件的大小是不知道的,可能大到内存放不下(你确定?<反正就是很大x>),本来想用wget
的,后来一想,无依赖做到底算了,和获取网页类似,不过这里是每次1kb然后写到文件中
int GetFile(char *url, char *file){
int length=0;
char buf[1024];
long unsigned int readDataLength;
FILE *fp;
HINTERNET hinternet=InternetOpen(0,INTERNET_OPEN_TYPE_PRECONFIG,0,0,0);
ASSERT(!hinternet,InternetCloseHandle(hinternet));
HINTERNET hinternetopen=InternetOpenUrl(hinternet,url,0,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
ASSERT(!hinternetopen,InternetCloseHandle(hinternet);InternetCloseHandle(hinternetopen));
length=0;
fp=fopen(file,"wb");
ASSERT(!fp,InternetCloseHandle(hinternetopen);InternetCloseHandle(hinternet));
do{
InternetReadFile(hinternetopen,buf,1024,&readDataLength);
fwrite(buf,1,readDataLength,fp);
length+=readDataLength;
}while(readDataLength);
InternetCloseHandle(hinternetopen);
InternetCloseHandle(hinternet);
fclose(fp);
return 1;
}
完整代码:Github