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

信息论的发展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. 46个Linux面试常见问题送给你

    问题一: 绝对路径用什么符号表示?当前目录.上层目录用什么表示?主目录用什么表示? 切换目录用什么命令? 答案:绝对路径: 如/etc/init.d当前目录和上层目录: ./  ../主目录: ~/切 ...

  2. 服务器安装centos

    谈一下今天遇到的problem,虽然很基础,但是还是值得记录一下: 1.制作启动盘,并不需要使用UltralISO刻录,可以通过在linux下dd命令直接制作iso镜像启动盘下面是步骤: 1)打开终端 ...

  3. JMockit常用操作

    JMockit常用操作 2017-11-30 转自:http://blog.csdn.net/foreverling/article/details/51234149 目录 1 基本概念  1.1 常 ...

  4. 错误代码和UNICODE编程

    程序错误处理 一般错误返回的数据类型有VOID BOOL HANDLE PVOID LONG/DWORD 返回值哪些代表成功和错误需查文档 错误码和解释存放在WinError.h中 使用GetLast ...

  5. Python3基础教程2——Python的标准数据类型

    2018年3月12日 这次介绍一些python里面的标准数据类型 当然还是推荐一个比较系统的教程 http://www.runoob.com/python3/python3-tutorial.html ...

  6. ie8兼容圆角

    ie8兼容圆角 PIE.HTC下载地址:http://css3pie.com/ 兼容ie8 代码如下: <!DOCTYPE html> <html> <head> ...

  7. centos上的grub文件修改

    centos上的grub文件修改 author:headsen chen 2017-10-10  17:36:42 个人原创,转载请注明作者和出处,否则追究法律责任 1,centos6上的修改:vim ...

  8. 优先级队列用法详解(priority_queue)

    由于优先级队列的内部数据结构为 堆,所以这里先介绍堆的一些操作. 堆的一些函数操作在algorithm头文件中 //在[first, last)范围内构造最大堆,first,last 可以是vecto ...

  9. Centos虚拟机克隆模板

    Centos6模板 IPTABLES/SELINUX # iptalbes -F # service iptables save 或 # /etc/init.d/iptables stop # chk ...

  10. 初探JodaTime

    在学习java之初时就使用过jdk自带的java.util.Calendar ,近期的项目中需要达到类似功能的时候使用了JodaTime. Joda-Time 令时间和日期值变得易于管理.操作和理解. ...