下面是一篇很有启发性的文章先分享给大家。

信息论的发展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请求抓取网页的简单实现的更多相关文章

  1. C语言Linix服务器网络爬虫项目(一)项目初衷和网络爬虫概述

    一.项目初衷和爬虫概述 1.项目初衷 本人的大学毕设就是linux上用c写的一个爬虫,现在我想把它完善起来,让他像一个企业级别的项目.为了重复发明轮子来学习轮子的原理,我们不使用第三方框架(这里是说的 ...

  2. [Python爬虫] 之二十七:Selenium +phantomjs 利用 pyquery抓取今日头条视频

    一.介绍 本例子用Selenium +phantomjs爬取今天头条视频(http://www.tvhome.com/news/)的信息,输入给定关键字抓取图片信息. 给定关键字:视频:融合:电视 二 ...

  3. [Python爬虫] 之二十三:Selenium +phantomjs 利用 pyquery抓取智能电视网数据

    一.介绍 本例子用Selenium +phantomjs爬取智能电视网(http://news.znds.com/article/news/)的资讯信息,输入给定关键字抓取资讯信息. 给定关键字:数字 ...

  4. [Python爬虫] 之二十一:Selenium +phantomjs 利用 pyquery抓取36氪网站数据

    一.介绍 本例子用Selenium +phantomjs爬取36氪网站(http://36kr.com/search/articles/电视?page=1)的资讯信息,输入给定关键字抓取资讯信息. 给 ...

  5. Python爬虫学习==>第十一章:分析Ajax请求-抓取今日头条信息

    学习目的: 解决AJAX请求的爬虫,网页解析库的学习,MongoDB的简单应用 正式步骤 Step1:流程分析 抓取单页内容:利用requests请求目标站点,得到单个页面的html代码,返回结果: ...

  6. 基于C#.NET的高端智能化网络爬虫(二)(攻破携程网)

    本篇故事的起因是携程旅游网的一位技术经理,豪言壮举的扬言要通过他的超高智商,完美碾压爬虫开发人员,作为一个业余的爬虫开发爱好者,这样的言论我当然不能置之不理.因此就诞生了以及这一篇高级爬虫的开发教程. ...

  7. Python即时网络爬虫项目启动说明

    作为酷爱编程的老程序员,实在按耐不下这个冲动,Python真的是太火了,不断撩拨我的心. 我是对Python存有戒备之心的,想当年我基于Drupal做的系统,使用php语言,当语言升级了,推翻了老版本 ...

  8. Python即时网络爬虫项目: 内容提取器的定义(Python2.7版本)

    1. 项目背景 在Python即时网络爬虫项目启动说明中我们讨论一个数字:程序员浪费在调测内容提取规则上的时间太多了(见上图),从而我们发起了这个项目,把程序员从繁琐的调测规则中解放出来,投入到更高端 ...

  9. Python即时网络爬虫项目: 内容提取器的定义

    1. 项目背景 在python 即时网络爬虫项目启动说明中我们讨论一个数字:程序员浪费在调测内容提取规则上的时间,从而我们发起了这个项目,把程序员从繁琐的调测规则中解放出来,投入到更高端的数据处理工作 ...

随机推荐

  1. ssh框架搭建出现的异常: class com.my.entity.user not found while looking for property: id

    在处理用户注册的时候,user实体的bean创建不出来,原代码如下: <class name="com.my.entity.User" table="user&qu ...

  2. NancyFX 第八章 内容协商

    在Web框架的范畴内,一切都是基于REST的-- 从返回包含CSS.JavaScript的网页的路由路径,到那些返回JSON数据的URL. 无论你怎么看它,两者都是必须的.我们使用一组URL来呈现UR ...

  3. 移动端tab滑动和上下拉刷新加载

    移动端tab滑动和上下拉刷新加载 查看demo(请在移动端模式下查看) 查看代码 开发该插件的初衷是,在做一个项目时发现现在实现移动端tab滑动的插件大多基于swiper,swiper的功能太强大而我 ...

  4. WPF自学入门(八)WPF窗体之间的交互

    今天我们一起来看一下WPF窗体之间的交互-窗体之间的传值.有两个窗体,一个是父窗体,一个是子窗体.要将父窗体的文本框中的值传递给子窗体中的控件.我们该怎么实现? 接下来我们一起来实现窗体之间的传值,在 ...

  5. redis笔记总结之redis介绍

    一.Redis介绍: redis的发展历史简单的理解为因为使用类似MySql这类关系型数据库不方便进而开发的开源的.轻量级的.非关系型的,直到现在一直不断完善的一款NoSql数据库.具体的介绍大家可以 ...

  6. RESTful接口设计原则和优点

    RESTful架构优点: 前后端分离,减少流量 安全问题集中在接口上,由于接受json格式,防止了注入型等安全问题 前端无关化,后端只负责数据处理,前端表现方式可以是任何前端语言(android,io ...

  7. ATM+购物商城完整版

    一,需求:模拟实现一个ATM + 购物商城程序 要求如下: 1.额度15000或者自定义 2.实现购物商城,买东西加入购物车,调用信用卡接口结账 3.可以提现,手续费5% 4.支持多账户登陆 5.支持 ...

  8. Selenium webdriver实现截图功能

    可参考http://www.cnblogs.com/tobecrazy/p/3599568.html Webdriver截图时,需要引入: import java.io.File; import ja ...

  9. 用js制作日期 2017-03-23

    日期表: <body> <select id="year" ></select>年 <select id="month" ...

  10. centos7服务的管理

    centos7上服务管理  author:headsen chen     2017-10-16  16:03:53       1,启动服务(每条都可以) systemctl start httpd ...