C语言Linix服务器网络爬虫项目(二)项目设计和通过一个http请求抓取网页的简单实现
下面是一篇很有启发性的文章先分享给大家。
信息论的发展https://zhuanlan.zhihu.com/p/20841617
我们通过上一篇了解了爬虫具体要实现的工作之后,我们分析得出的网络爬虫的基本工作流程如下:
1.首先选取一部分精心挑选的种子URL;
2.将这些URL放入待抓取URL队列;
3.从待抓取URL队列中取出待抓取在URL,解析DNS,并且得到主机的ip,并将URL对应的网页下载下来,存储进已下载网页库中。此外,将这些URL放进已抓取URL队列。
4.分析已抓取URL队列中的URL,分析其中的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环。
一、爬虫设计
从爬虫的角度对互联网进行划分,可以将互联网的所有页面分为五个部分:
1.已下载未过期网页
2.已下载已过期网页:抓取到的网页实际上是互联网内容的一个镜像与备份,互联网是动态变化的,一部分互联网上的内容已经发生了变化,这时,这部分抓取到的网页就已经过期了。
3.待下载网页:也就是待抓取URL队列中的那些页面
4.可知网页:还没有抓取下来,也没有在待抓取URL队列中,但是可以通过对已抓取页面或者待抓取URL对应页面进行分析获取到的URL,认为是可知网页。
5.还有一部分网页,爬虫是无法直接抓取下载的。称为不可知网页。
我们爬虫项目的主事件流程大致如下:
1.获取命令行参数,执行相应操作
2.读取配置文件,解析得到各种设置
3.载入各种模块
4.种子入队,开启DNS解析线程(原始队列不为空时解析)
5.创建epoll,开启任务,发起请求等等,关注事件
6.while大循环中使用epoll_wait返回活跃的事件,每个事件开启一个线程处理(线程中主要是解析页面,保存页面,url处理等),在线程结束的时候可能会开启新的任务。(或者程序初始化时创建线程池,在没任务时阻塞线程,通过pthread_cond_signal来唤醒睡眠队列中的线程,但是一个页面分析出的有效url会很多,这时候我们甚至需要在队列满时阻塞分析页面获得url的线程,使用线程池的优点就是减少了线程创建和销毁的系统开销)
在爬虫系统中,待抓取URL队列是很重要的一部分。待抓取URL队列中的URL以什么样的顺序排列也是一个很重要的问题,因为这涉及到先抓取那个页面,后抓取哪个页面。而决定这些URL排列顺序的方法,叫做抓取策略。下面重点介绍几种常见的抓取策略(关于爬取策略优劣分析的建议大家读一下吴军先生的《数学之美》的第九章和第十章):
1.深度优先遍历策略
深度优先遍历策略是指网络爬虫会从起始页开始,一个链接一个链接跟踪下去,处理完这条线路之后再转入下一个起始页,继续跟踪链接。
2.广度优先遍历策略
广度优先遍历策略的基本思路是,将新下载网页中发现的链接直接插入待抓取URL队列的末尾。也就是指网络爬虫会先抓取起始网页中链接的所有网页,然后再选择其中的一个链接网页,继续抓取在此网页中链接的所有网页。还是以上面的图为例:
3.反向链接数策略
反向链接数是指一个网页被其他网页链接指向的数量。反向链接数表示的是一个网页的内容受到其他人的推荐的程度。因此,很多时候搜索引擎的抓取系统会使用这个指标来评价网页的重要程度,从而决定不同网页的抓取先后顺序。
在真实的网络环境中,由于广告链接、作弊链接的存在,反向链接数不能完全等他我那个也的重要程度。因此,搜索引擎往往考虑一些可靠的反向链接数。
4.Partial PageRank策略
Partial PageRank算法借鉴了PageRank算法的思想:对于已经下载的网页,连同待抓取URL队列中的URL,形成网页集合,计算每个页面的PageRank值,计算完之后,将待抓取URL队列中的URL按照PageRank值的大小排列,并按照该顺序抓取页面。
如果每次抓取一个页面,就重新计算PageRank值,一种折中方案是:每抓取K个页面后,重新计算一次PageRank值。但是这种情况还会有一个问题:对于已经下载下来的页面中分析出的链接,也就是我们之前提到的未知网页那一部分,暂时是没有PageRank值的。为了解决这个问题,会给这些页面一个临时的PageRank值(比如1):将这个网页所有入链传递进来的PageRank值进行汇总(其实就是反复进行大矩阵运算,未知站的PageRank值会逐渐收敛到他应有的值,说实话收敛是我个人认为这个算法最美的地方),这样就形成了该未知页面的PageRank值,从而参与排序。
5.OPIC策略策略
该算法实际上也是对页面进行一个重要性打分。在算法开始前,给所有页面一个相同的初始现金(cash)。当下载了某个页面P之后,将P的现金分摊给所有从P中分析出的链接,并且将P的现金清空。对于待抓取URL队列中的所有页面按照现金数进行排序。
6.大站优先策略
对于待抓取URL队列中的所有网页,根据所属的网站进行分类。对于待下载页面数多的网站,优先下载。这个策略也因此叫做大站优先策略。
下面
二、通过一个http请求抓取网页的html存储到文件的简单实现
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<string.h>
#include<sys/socket.h>
#include<netdb.h>
#include<unistd.h>
#include<fcntl.h> #define MAX_URL_LEN 1024
#define MAX_FILE_NAME_LEN 64
#define MAX_REUQEST_LEN 1024
#define BUFF_MAX_SIZE 512
#define PAGE_MAX_SIZE 4096*128
void parseURL(char * url,char* host,char* path)
{
//char tmp[MAX_URL_LEN] = {0};
char*ptmp = NULL;
strcpy(host,url);
if((ptmp = strstr(url,"http://")) != NULL)//https format
{
ptmp = ptmp + ;
strcpy(host,ptmp);
}else if(ptmp = NULL,(ptmp = strstr(url,"https://")) != NULL)//http format
{
ptmp = ptmp + ;
strcpy(host,ptmp);
}
ptmp = NULL;
if((ptmp = strpbrk(host,"/")) != NULL)
{
strcpy(path,ptmp);
ptmp[] = '\0';
} }
void getPage(char* host,char* path,char* file)
{
struct hostent *phost;
if( == (phost = gethostbyname(host)))
{
printf("host err\n");
exit();
} struct sockaddr_in pin;
int port = ;
bzero(&pin,sizeof(pin));
pin.sin_family=AF_INET;
pin.sin_port=htons(port);
pin.sin_addr.s_addr=((struct in_addr*)(phost->h_addr))->s_addr;
int isock;
if((isock = socket(AF_INET,SOCK_STREAM,)) == -)
{
printf("socket err\n");
exit();
}
char requestHeader[MAX_REUQEST_LEN] = "GET ";
strcat(requestHeader,path);
strcat(requestHeader," HTTP/1.0\r\nHost: ");
strcat(requestHeader,host);
strcat(requestHeader,"\r\nAccept: */*\r\n");
strcat(requestHeader,"User-Agent: Mozilla/4.0(compatible)\r\n");
strcat(requestHeader,"Connection: Keep-Alive\r\n");
strcat(requestHeader,"\r\n"); if(connect(isock,(struct sockaddr*)&pin,sizeof(pin)) == -)
{
printf("connect err\n");
exit();
} if(send(isock,requestHeader,strlen(requestHeader),) == -)
{
printf("send err\n");
exit();
}
//struct timeval timeout={1,0};
//setsockopt(isock,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));
char buffer[BUFF_MAX_SIZE];
char page[PAGE_MAX_SIZE];
int len;
printf("Start fetch\n");
int fd = open("file",O_RDWR|O_CREAT,);
int flag = ;
char tmpch;
//while(recv(isock,&tmpch,sizeof(char))>)
//{
// if(tmpch == '\r')
// {
// 如何读到一个http请求头的末尾?
// http://www.runoob.com/http/http-messages.html
// }
//}
while((len = recv(isock,buffer,BUFF_MAX_SIZE-,))>)
{
buffer[len]='\0'; write(fd,buffer,strlen(buffer)+); }
close(isock);
close(fd);
} int main()
{
char url[MAX_URL_LEN] = "http://www.runoob.com/http/http-intro.html";
//char url[MAX_URL_LEN] = "https://www.runoob.com/http/http-intro.html";
char host[MAX_URL_LEN] = {};
char path[MAX_URL_LEN] = {};
char file[MAX_FILE_NAME_LEN] = "file"; //parse url to get host and page path
parseURL(url,host,path);
//puts(host);
//puts(path);
//connect and sv the page into a file
getPage(host,path,file); }
下一篇我们将分析这个小程序所做的事情,虽然他很小,却把包含了一个爬虫所要做的大部分内容。
C语言Linix服务器网络爬虫项目(二)项目设计和通过一个http请求抓取网页的简单实现的更多相关文章
- C语言Linix服务器网络爬虫项目(一)项目初衷和网络爬虫概述
一.项目初衷和爬虫概述 1.项目初衷 本人的大学毕设就是linux上用c写的一个爬虫,现在我想把它完善起来,让他像一个企业级别的项目.为了重复发明轮子来学习轮子的原理,我们不使用第三方框架(这里是说的 ...
- [Python爬虫] 之二十七:Selenium +phantomjs 利用 pyquery抓取今日头条视频
一.介绍 本例子用Selenium +phantomjs爬取今天头条视频(http://www.tvhome.com/news/)的信息,输入给定关键字抓取图片信息. 给定关键字:视频:融合:电视 二 ...
- [Python爬虫] 之二十三:Selenium +phantomjs 利用 pyquery抓取智能电视网数据
一.介绍 本例子用Selenium +phantomjs爬取智能电视网(http://news.znds.com/article/news/)的资讯信息,输入给定关键字抓取资讯信息. 给定关键字:数字 ...
- [Python爬虫] 之二十一:Selenium +phantomjs 利用 pyquery抓取36氪网站数据
一.介绍 本例子用Selenium +phantomjs爬取36氪网站(http://36kr.com/search/articles/电视?page=1)的资讯信息,输入给定关键字抓取资讯信息. 给 ...
- Python爬虫学习==>第十一章:分析Ajax请求-抓取今日头条信息
学习目的: 解决AJAX请求的爬虫,网页解析库的学习,MongoDB的简单应用 正式步骤 Step1:流程分析 抓取单页内容:利用requests请求目标站点,得到单个页面的html代码,返回结果: ...
- 基于C#.NET的高端智能化网络爬虫(二)(攻破携程网)
本篇故事的起因是携程旅游网的一位技术经理,豪言壮举的扬言要通过他的超高智商,完美碾压爬虫开发人员,作为一个业余的爬虫开发爱好者,这样的言论我当然不能置之不理.因此就诞生了以及这一篇高级爬虫的开发教程. ...
- Python即时网络爬虫项目启动说明
作为酷爱编程的老程序员,实在按耐不下这个冲动,Python真的是太火了,不断撩拨我的心. 我是对Python存有戒备之心的,想当年我基于Drupal做的系统,使用php语言,当语言升级了,推翻了老版本 ...
- Python即时网络爬虫项目: 内容提取器的定义(Python2.7版本)
1. 项目背景 在Python即时网络爬虫项目启动说明中我们讨论一个数字:程序员浪费在调测内容提取规则上的时间太多了(见上图),从而我们发起了这个项目,把程序员从繁琐的调测规则中解放出来,投入到更高端 ...
- Python即时网络爬虫项目: 内容提取器的定义
1. 项目背景 在python 即时网络爬虫项目启动说明中我们讨论一个数字:程序员浪费在调测内容提取规则上的时间,从而我们发起了这个项目,把程序员从繁琐的调测规则中解放出来,投入到更高端的数据处理工作 ...
随机推荐
- 前端知识点总结——VUE
转载自:http://www.bslxx.com/m/view.php?aid=1799 1.框架和库的区别: 框架:framework 有着自己的语法特点.都有对应的各个模块库 library 专注 ...
- Django Middleware简介
1 前言 Django使用非常熟练了,各种API接口不在话下,全都搞定.为方便定位问题在每个API接口的的开始和返回的地方都加上了log打印,记录入参和返回值. 但是这样有一个问题,需要每个 ...
- 关系型数据库工作原理-事务管理(二)(翻译自Coding-Geek文章)
本文翻译自Coding-Geek文章:< How does a relational database work>. 原文链接:http://coding-geek.com/how-dat ...
- 将PPT文件内容转换为图片放在Email邮件正文中发送
通过Email推送统计报告.一般除了要求将PPT报告文件作为附件发给用户,同时希望将报告内容在邮件中直观展示. 一份统计报告中经常包含柱状图.饼图.好看的图表,这些信息要直接在Email中展示比较复杂 ...
- sharepoint 2013实践
之前在一篇文章中说过了SharePoint环境的安装.那么如何使用SharePoint开发一个站点呢?这就是本篇所要阐述的问题. 在如何具体操作之前,我们先来普及下SharePoint基础知识.Far ...
- token的时限多长才合适?
在使用JWT时,一个让人纠结的问题就是"Token的时限多长才合适?".对此,Stormpath的这篇文章给出了一个可供参考的建议: 面对极度敏感的信息,如钱或银行数据,那就根本不 ...
- [转]ICE介绍 (RFC 5245)
[转]ICE介绍 (RFC 5245) http://blog.csdn.net/dxpqxb/article/details/22040017 1关于ICE的10个事实 1 ICE使用STUN和TU ...
- 解决Win10下_findnext()异常
在win10中,使用文件遍历函数_findnext会报0xC0000005错误 ,发生访问冲突错误 错误定位到ntdll.dll 原因: _findnext()第一个参数"路径句柄" ...
- pc端响应式-媒体查询
媒体查询(@media):能在不同的条件下使用不同的样式,使页面在不同在终端设备下达到不同的渲染效果 列举常用的pc屏幕宽度: 1024 1280 1366 1440 1680 1920 ...
- 教你如何前后端完全分离(非api、ajax)
我的前后分离,不是api,不是ajax,我这里只讨论html与后端结合 前话 曾经风靡一时的dedecms相信做网站的十有八.九都知道,还有那么一些不是技术出生的人,通过看一下文档,也能访问出网站出来 ...