网络爬虫草稿

本文介绍了一款基于Winsock的简易Web爬虫程序设计与实现,该爬虫采用深度优先搜索策略,能够抓取并解析网页,提取链接进行进一步爬取。文章详细展示了程序代码,并指出了存在的不足之处,如效率低下、链接判断不准确等问题。

 为了网络保存,还是发出来,后天去一搜索引擎公司实习,就写了一个小爬虫,以前从没接触过,写得很烂,只能作为草稿,以后有时间的话再改,实现了一个基本功能就是爬出一些网页来

 

说明:

 

1.基于winsock写的

2.爬网页采用深度优先方式,用递归实现的,实际应该自己写栈实现吧,不然容易栈溢出

3.解析网页我采用直接从硬盘一个个字符读数据,导致速度巨慢,应当先读入内存中再处理

4.合法的url判断不够准确,爬出一些非网页出来,或者一些正常网页又爬不出来

5.没有进行网页判重,即同一网页可能被搜索两次,这可以用hash表实现判重

6.http请求报头很随意

 

 

 等等还有很多缺点,不过一点收获是知道了爬虫程序最基本的应该做些啥

 

#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
#define DEFAULT_COUNT       1
#define DEFAULT_PORT        80
#define DEFAULT_BUFFER      2048
#define NAMELEN             100
 
#define FIRSTURL  "http://www.163.com/"
#define FIRSTWEB  "www.163.com"
 
#define MAXDEPTH  5         //递归深度
#define MAXWEBLEN 50        
#define MAXURLLEN 200     
#define MAXWEB 30          //抓取的页面数
char  szServer[128],          // Server to connect to
      szMessage[1024],        // Message to send to sever
 
int  iPort= DEFAULT_PORT;  // Port on server to connect to
 
int flag;
 
 
char  szBuffer[DEFAULT_BUFFER];
 
int count=1;  
 
//删除http响应报头
void Skiphead(FILE* f)
{
char s[100];
while(1)
{
fgets(s,100,f);
if(s[0]=='/n'||s[0]=='/r') return;
}
}
 
//http 请求报头
void Requestmessage(char* url)
{
szMessage[0]=0;
strcat(szMessage,"GET ");
strcat(szMessage,url);
strcat(szMessage," HTTP/1.1/r/n");
strcat(szMessage,"Connection: close/r/n");
strcat(szMessage,"User-agent: Mozilla/4.0/r/n");
strcat(szMessage,"Accept: text/html, image/gif, image/jpeg/r/n");
     strcat(szMessage,"Accept-language:zh-cn/r/n");
strcat(szMessage,"/r/n");
}
 
//创建一个新的页面
int Creatweb(char* name)
{
FILE* tf=fopen("temp.html","r");
//char name[NAMELEN];
char temp[10];
    char c;
char no[10];
 
if(fscanf(tf,"%c",&c)==EOF)
{
printf("temp.html 内容为空,抓取失败/n");
return 0;
}
while(1)
{
if(fscanf(tf,"%c",&c)==EOF)
{
printf("网页内容不含标题/n");
return 0;
}
if(c=='t'||c=='T')
{
if(fscanf(tf,"%c%c%c%c%c",temp,temp+1,temp+2,temp+3,temp+4)==EOF)
{
   printf("网页内容不含标题/n");
   return 0;
} 
temp[5]=0;
if((strcmp(temp,"itle>")==0)||(strcmp(temp,"ITLE>")==0))
{
                int i=0;
fscanf(tf,"%c",&c);
while(c!='<')
{
name[i++]=c;
fscanf(tf,"%c",&c);
}
name[i]=0;
break;
}
 
}
}
 
    memset(no,0,sizeof(no));
    sprintf(no,"_%d",count++);
strcat(name,no);
strcat(name,".html");
 
    fseek(tf,0,SEEK_SET);
 
    Skiphead(tf);
 
FILE* nf=fopen(name,"w");
while(fscanf(tf,"%c",&c)!=EOF)
{
fprintf(nf,"%c",c);
fflush(nf);
}
 
fclose(tf);
fclose(nf);
 
printf("抓取页面: %s/n",name);
 
if(count-1==MAXWEB)
{
printf("共抓取 %d 个页面/n",count-1);
WSACleanup();
exit(0);
}
 
return 1;
 
}
 
//从url解析出域名
int Getweb(char* url,char* web)
{   
char* s=url;
char* t=web;
    if(*s=='h'&&*(s+1)=='t'&&*(s+2)=='t'&&*(s+3)=='p')s+=7;
else {
              printf("非合法的url:%s/n",url);
 return 0;
}
while(*s&&*s!='/') *web++=*s++;
*web=0;
 
printf("sever web:%s/n",t);
return 1;
}
 
void Crawlweb(char* url,int depth);
 
void AnalyseHtml(char* name,int depth)
{
 
if(depth+1>MAXDEPTH) return;
 
    FILE* file=fopen(name,"r");
char nurl[MAXURLLEN];
char hr[10];
 
int i=0;
char c;
while(fscanf(file,"%c",&c)!=EOF)
{
 
        if(c=='h')
{
           if(fscanf(file,"%c%c%c%c%c",hr,hr+1,hr+2,hr+3,hr+4)==EOF) break;
  hr[5]=0;
  if(strcmp(hr,"ref=/"")==0)
  {
  i=0;
  fscanf(file,"%c",&c);
  while(c!='/"')
  {
  nurl[i++]=c;
  fscanf(file,"%c",&c);
  }
  nurl[i]=0;
//   printf("nurl:%s/n",nurl);
  Crawlweb(nurl,depth+1);
  }
}
 
}
 
fclose(file);
 
}
 
 
 
// url:待分析url depth:递归深度
void Crawlweb(char* url,int depth)
{
     if(depth>MAXDEPTH) return;
 
printf("crawl url:%s/n",url);
 
SOCKET        sClient;
 
int           ret;
     struct sockaddr_in server;
     struct hostent    *host = NULL;
 
FILE* webfile;
webfile=fopen("temp.html","w");
     char name[NAMELEN];
char web[MAXWEBLEN];
 
 
if(!Getweb(url,web)) return ;
Requestmessage(url);
 
 
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET)
{
printf("socket() failed: %d/n", WSAGetLastError());
exit(1);
}
 
server.sin_family = AF_INET;
     server.sin_port = htons(iPort);
 
host = gethostbyname(web);
if (host == NULL)
{
printf("Unable to resolve server: %s/n", szServer);
return ;
//	 exit(1);
}
CopyMemory(&server.sin_addr, host->h_addr_list[0],
host->h_length);
 
 
if (connect(sClient, (struct sockaddr *)&server, 
sizeof(server)) == SOCKET_ERROR)
{
printf("connect() failed: %d/n", WSAGetLastError());
return ;
// exit(1);
}
 
 
 
 
//发送http请求报文
ret = send(sClient, szMessage, strlen(szMessage), 0);
if (ret == 0)
{
printf("send 0 byte failed: %d/n");
exit(1);
}
else if (ret == SOCKET_ERROR)
{
printf("send() failed: %d/n", WSAGetLastError());
exit(1);
}
printf("Send %d bytes/n", ret);
 
//抓取网页
int ff=1;
int cnt=0;
while(ret!=0)
{
ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
cnt+=ret;
if (ret == 0)     
break;
else if (ret == SOCKET_ERROR)
{
printf("recv() failed: %d/n", WSAGetLastError());
break;
}
szBuffer[ret] = '/0';
 
fprintf(webfile,"%s",szBuffer);
fflush(webfile);
}
 
    if(cnt&&Creatweb(name)) AnalyseHtml(name,depth);
 
closesocket(sClient);
fclose(webfile);
 
}
 
 
int main(int argc, char **argv)
{
    WSADATA       wsd;
    count=1;
    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
        printf("Failed to load Winsock library!/n");
        return 1;
    }
 
Crawlweb(FIRSTURL,0);
    WSACleanup();
    return 0;
}


 

内容概要:本文介绍了一个基于多传感器融合的定位系统设计方案,采用GPS、里程计和电子罗盘作为定位传感器,利用扩展卡尔曼滤波(EKF)算法对多源传感器数据进行融合处理,最终输出目标的滤波后位置信息,并提供了完整的Matlab代码实现。该方法有效提升了定位精度与稳定性,尤其适用于存在单一传感器误差或信号丢失的复杂环境,如自动驾驶、移动采用GPS、里程计和电子罗盘作为定位传感器,EKF作为多传感器的融合算法,最终输出目标的滤波位置(Matlab代码实现)机器人导航等领域。文中详细阐述了各传感器的数据建模方式、状态转移与观测方程构建,以及EKF算法的具体实现步骤,具有较强的工程实践价值。; 适合人群:具备一定Matlab编程基础,熟悉传感器原理和滤波算法的高校研究生、科研人员及从事自动驾驶、机器人导航等相关领域的工程技术人员。; 使用场景及目标:①学习和掌握多传感器融合的基本理论与实现方法;②应用于移动机器人、无人车、无人机等系统的高精度定位与导航开发;③作为EKF算法在实际工程中应用的教学案例或项目参考; 阅读建议:建议读者结合Matlab代码逐行理解算法实现过程,重点关注状态预测与观测更新模块的设计逻辑,可尝试引入真实传感器数据或仿真噪声环境以验证算法鲁棒性,并进一步拓展至UKF、PF等更高级滤波算法的研究与对比。
内容概要:文章围绕智能汽车新一代传感器的发展趋势,重点阐述了BEV(鸟瞰图视角)端到端感知融合架构如何成为智能驾驶感知系统的新范式。传统后融合与前融合方案因信息丢失或算力需求过高难以满足高阶智驾需求,而基于Transformer的BEV融合方案通过统一坐标系下的多源传感器特征融合,在保证感知精度的同时兼顾算力可行性,显著提升复杂场景下的鲁棒性与系统可靠性。此外,文章指出BEV模型落地面临大算力依赖与高数据成本的挑战,提出“数据采集-模型训练-算法迭代-数据反哺”的高效数据闭环体系,通过自动化标注与长尾数据反馈实现算法持续进化,降低对人工标注的依赖,提升数据利用效率。典型企业案例进一步验证了该路径的技术可行性与经济价值。; 适合人群:从事汽车电子、智能驾驶感知算法研发的工程师,以及关注自动驾驶技术趋势的产品经理和技术管理者;具备一定自动驾驶基础知识,希望深入了解BEV架构与数据闭环机制的专业人士。; 使用场景及目标:①理解BEV+Transformer为何成为当前感知融合的主流技术路线;②掌握数据闭环在BEV模型迭代中的关键作用及其工程实现逻辑;③为智能驾驶系统架构设计、传感器选型与算法优化提供决策参考; 阅读建议:本文侧重技术趋势分析与系统级思考,建议结合实际项目背景阅读,重点关注BEV融合逻辑与数据闭环构建方法,并可延伸研究相关企业在舱泊一体等场景的应用实践。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值