当我们设计好程序框架之后就要开始实现它了。第一步当然是要实现主程序的流程框架。之后我们逐渐填充每个流程的细节和其需要调用的模块。

主程序的流程如下:

1、  解析命令行参数,并根据参数跳转到相应的处理分支

2、  解析配置文件

3、  载入处理模块

4、  加载种子URL

5、  启动抓取任务

主程序的代码如下:

int main(int argc, void *argv[])
{
struct epoll_event events[10];
int daemonized = 0;
char ch; while ((ch = getopt(argc, (char* const*)argv, "vhd")) != -1) {
switch(ch) {
case 'v':
version();
break;
case 'd':
daemonized = 1;
break;
case 'h':
case '?':
default:
usage();
}
} g_conf = initconfig();
loadconfig(g_conf); set_nofile(1024); vector<char *>::iterator it = g_conf->modules.begin();
for(; it != g_conf->modules.end(); it++) {
dso_load(g_conf->module_path, *it);
} if (g_conf->seeds == NULL) {
SPIDER_LOG(SPIDER_LEVEL_ERROR, "Wehave no seeds, Buddy!");
} else {
int c = 0;
char ** splits =strsplit(g_conf->seeds, ',', &c, 0);
while (c--) {
Surl * surl = (Surl*)malloc(sizeof(Surl));
surl->url =url_normalized(strdup(splits[c]));
surl->level = 0;
surl->type = TYPE_HTML;
if (surl->url != NULL)
push_surlqueue(surl);
}
} if (daemonized)
daemonize(); chdir("download"); int err = -1;
if ((err = create_thread(urlparser, NULL, NULL, NULL)) < 0) {
SPIDER_LOG(SPIDER_LEVEL_ERROR,"Create urlparser thread fail: %s", strerror(err));
} int try_num = 1;
while(try_num < 8 && is_ourlqueue_empty())
usleep((10000 << try_num++)); if (try_num >= 8) {
SPIDER_LOG(SPIDER_LEVEL_ERROR, "NOourl! DNS parse error?");
} if (g_conf->stat_interval > 0) {
signal(SIGALRM, stat);
set_ticker(g_conf->stat_interval);
} int ourl_num = 0;
g_epfd = epoll_create(g_conf->max_job_num); while(ourl_num++ < g_conf->max_job_num) {
if (attach_epoll_task() < 0)
break;
} int n, i;
while(1) {
n = epoll_wait(g_epfd, events, 10,2000);
printf("epoll:%d\n",n);
if (n == -1)
printf("epollerrno:%s\n",strerror(errno));
fflush(stdout); if (n <= 0) {
if (g_cur_thread_num <= 0&& is_ourlqueue_empty() && is_surlqueue_empty()) {
sleep(1);
if (g_cur_thread_num <= 0&& is_ourlqueue_empty() && is_surlqueue_empty())
break;
}
} for (i = 0; i < n; i++) {
evso_arg * arg = (evso_arg*)(events[i].data.ptr);
if ((events[i].events &EPOLLERR) ||
(events[i].events &EPOLLHUP) ||
(!(events[i].events &EPOLLIN))) {
SPIDER_LOG(SPIDER_LEVEL_WARN,"epoll fail, close socket %d",arg->fd);
close(arg->fd);
continue;
}
epoll_ctl(g_epfd, EPOLL_CTL_DEL,arg->fd, &events[i]); /* del event */ printf("helloepoll:event=%d\n",events[i].events);
fflush(stdout);
create_thread(recv_response, arg,NULL, NULL);
}
} SPIDER_LOG(SPIDER_LEVEL_DEBUG, "Task done!");
close(g_epfd);
return 0;
}

Linux企业级项目实践之网络爬虫(4)——主程序流程的更多相关文章

  1. Linux企业级项目实践之网络爬虫(1)——项目概述及准备工作

    我们在学习了Linux系统编程之后,需要一些实战项目来提高自己的水平,本系列我们通过编写一个爬虫程序,将我们学习的知识进行综合应用,同时在实现项目的过程中逐渐养成一些有用的思维方式,并具有初步的软件开 ...

  2. Linux企业级项目实践之网络爬虫(29)——遵守robots.txt

    Robots协议(也称为爬虫协议.机器人协议等)的全称是"网络爬虫排除标准"(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以 ...

  3. Linux企业级项目实践之网络爬虫(21)——扩展为多任务爬虫

    高效的网络爬虫是搜索引擎的重要基础.采用多任务并发执行,实现类似于CPU的流水线(pipeline)运行方式,可极大地提高网络和计算资源的利用率等性能. #include "threads. ...

  4. Linux企业级项目实践之网络爬虫(2)——网络爬虫的结构与工作流程

    网络爬虫是捜索引擎抓取系统的重要组成部分.爬虫的主要目的是将互联网上的网页下载到本地形成一个或联网内容的镜像备份. 一个通用的网络爬虫的框架如图所示:

  5. Linux企业级项目实践之网络爬虫(23)——系统测试:找出系统中的bug

    为了验证爬虫的业务流程.性能和健壮性需要进行测试. 软件测试是描述一种用来促进鉴定软件的正确性.完整性.安全性和质量的过程.软件测试的经典定义是:在规定的条件下对程序进行操作,以发现程序错误,衡量软件 ...

  6. Linux企业级项目实践之网络爬虫(28)——爬虫socket处理

    Socket是进程之间交换数据的机制.这些进程即可以是同一台机器上的,也可以是通过网络连接起来的不同机器.一旦一个Socket连接建立,那么数据就能够双向传输,直到其中一端关闭连接. 通常,请求数据的 ...

  7. Linux企业级项目实践之网络爬虫(19)——epoll接口

    由于要实现爬虫程序的快速抓取,显然如果采用阻塞型的I/O方式,那么系统可能很长时间都处在等待内核响应的状态中,这样爬虫程序将大大地降低效率.然而,如果采用非阻塞I/O,那么就要一直调用应用进程,反复对 ...

  8. Linux企业级项目实践之网络爬虫(6)——将程序设计成为守护进程

    在linux或者unix操作系统中在系统的引导的时候会开启很多服务,这些服务就叫做守护进程.为了增加灵活性,root可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别以一定的方式配置系统. ...

  9. Linux企业级项目实践之网络爬虫(3)——设计自己的网络爬虫

    网络抓取系统分为核心和扩展组件两部分.核心部分是一个精简的.模块化的爬虫实现,而扩展部分则包括一些便利的.实用性的功能.目标是尽量的模块化,并体现爬虫的功能特点.这部分提供简单.灵活的API,在基本不 ...

  10. Linux企业级项目实践之网络爬虫(30)——通过查阅RFC文档扩充更加复杂的功能

    HTTP是一种很简单的请求.响应式协议,客户端发送一个请求.服务器返回一个响应.HTTP 1.1 版本规范由 RFC2616 定义.了解了 HTTP请求.响应消息在TCP数据流中的格式,很容易使用纯 ...

随机推荐

  1. java与数据结构(6)---java实现链栈

    栈之链式存储结构链栈 链栈 栈的链式存储结构成为链栈.链栈是没有头结点,头结点就是栈顶指针top. 代码结构 package list; public interface Stackable;公共接口 ...

  2. Java设计模式之简单工厂、工厂方法和抽象工厂

    在前面的学习中(参见前面的博客),我们学到了很多OO原则: 封装变化 多用组合,少用继承 针对接口/超类编程,不针对实现编程 松耦合 开闭原则 让我们从一个简单的类开始,看看如何将之改造成符合OO原则 ...

  3. Linux 系统下查看硬件信息命令大全

    有许多命令可以用来查看 Linux 系统上的硬件信息.有些命令只能够打印出像 CPU 和内存这一特定的硬件组件信息,另外一些命令可以查看多种硬件组件的信息. 这个教程可以带大家快速了解一下查看各种硬件 ...

  4. Java框架学习之Hibernate入门

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hibernate可以应用在任何使用JDB ...

  5. flume的自定义sink-Kafka

    1.创建一个agent,sink类型需指定为自定义sink        vi /usr/local/flume/conf/agent3.conf        agent3.sources=as1  ...

  6. 形形色色的软件生命周期模型(4)——MSF、实用型

    摘要: 读大学时,我们曾经学习过不少软件生命周期模型,当时还不是很懂软件开发,你可能会觉得这些东西很新奇.在实际工作中,你会发现这些模型其实很难应用,与此同时你会接触到RUP.MSF等权威软件公司的生 ...

  7. AIR加载PDF

    //系统需要先安装上Adobe Reader import flash.html.HTMLLoader; import flash.html.HTMLPDFCapability; import fla ...

  8. 流媒体开发之-腾讯体育NBA视频点播解析

    在前面解析赛事和排名,在这里解析点播视频,选取的是腾讯体育链接里面的点播. 首先还是先封装一个保存点播视频的相关信息的类 package com.jwzhangjie.model; import ja ...

  9. struts2.1.3之后使用自定义Filter

    struts2中 ActionContextCleanUp, StrutsPrepareAndExecuteFilter, StrutsPrepareFilter,StrutsExecuteFilte ...

  10. android学习笔记---63-PopupWindow,泡泡窗口的实现

    转载http://blog.csdn.net/lidew521/article/details/8976627 PopupWindow是一个可以显示在当前Activity之上的浮动容器,PopupWi ...