1. int main(int argc, void *argv[])
  2. {
  3. struct epoll_event events[];
  4. int daemonized = ;
  5. char ch;
  6.  
  7. while ((ch = getopt(argc, (char* const*)argv, "vhd")) != -) {
  8. switch(ch) {
  9. case 'v':
  10. version();
  11. break;
  12. case 'd':
  13. daemonized = ;
  14. break;
  15. case 'h':
  16. case '?':
  17. default:
  18. usage();
  19. }
  20. }
  21.  
  22. g_conf = initconfig();
  23. loadconfig(g_conf);
  24.  
  25. set_nofile();
  26.  
  27. vector<char *>::iterator it = g_conf->modules.begin();
  28. for(; it != g_conf->modules.end(); it++) {
  29. dso_load(g_conf->module_path, *it);
  30. }
  31.  
  32. if (g_conf->seeds == NULL) {
  33. SPIDER_LOG(SPIDER_LEVEL_ERROR, "We have no seeds!");
  34. } else {
  35. int c = ;
  36. char ** splits = strsplit(g_conf->seeds, ',', &c, );
  37. while (c--) {
  38. Surl * surl = (Surl *)malloc(sizeof(Surl));
  39. surl->url = url_normalized(strdup(splits[c]));
  40. surl->level = ;
  41. surl->type = TYPE_HTML;
  42. if (surl->url != NULL)
  43. push_surlqueue(surl);
  44. }
  45. }
  46.  
  47. if (daemonized)
  48. daemonize();
  49.  
  50. chdir("download");
  51.  
  52. int err = -;
  53. if ((err = create_thread(urlparser, NULL, NULL, NULL)) < ) {
  54. SPIDER_LOG(SPIDER_LEVEL_ERROR, "Create urlparser thread fail: %s", strerror(err));
  55. }
  56.  
  57. /* waiting seed ourl ready */
  58. int try_num = ;
  59. while(try_num < && is_ourlqueue_empty())
  60. usleep(( << try_num++));
  61.  
  62. if (try_num >= ) {
  63. SPIDER_LOG(SPIDER_LEVEL_ERROR, "NO ourl! DNS parse error?");
  64. }
  65.  
  66. /* set ticker */
  67. if (g_conf->stat_interval > ) {
  68. signal(SIGALRM, stat);
  69. set_ticker(g_conf->stat_interval);
  70. }
  71.  
  72. /* begin create epoll to run */
  73. int ourl_num = ;
  74. g_epfd = epoll_create(g_conf->max_job_num);
  75.  
  76. while(ourl_num++ < g_conf->max_job_num) {
  77. if (attach_epoll_task() < )
  78. break;
  79. }
  80.  
  81. /* epoll wait */
  82. int n, i;
  83. while() {
  84. n = epoll_wait(g_epfd, events, , );
  85. printf("epoll:%d\n",n);
  86. if (n == -)
  87. printf("epoll errno:%s\n",strerror(errno));
  88. fflush(stdout);
  89.  
  90. if (n <= ) {
  91. if (g_cur_thread_num <= && is_ourlqueue_empty() && is_surlqueue_empty()) {
  92. sleep();
  93. if (g_cur_thread_num <= && is_ourlqueue_empty() && is_surlqueue_empty())
  94. break;
  95. }
  96. }
  97.  
  98. for (i = ; i < n; i++) {
  99. evso_arg * arg = (evso_arg *)(events[i].data.ptr);
  100. if ((events[i].events & EPOLLERR) ||
  101. (events[i].events & EPOLLHUP) ||
  102. (!(events[i].events & EPOLLIN))) {
  103. SPIDER_LOG(SPIDER_LEVEL_WARN, "epoll fail, close socket %d",arg->fd);
  104. close(arg->fd);
  105. continue;
  106. }
  107.  
  108. epoll_ctl(g_epfd, EPOLL_CTL_DEL, arg->fd, &events[i]); /* del event */
  109.  
  110. printf("hello epoll:event=%d\n",events[i].events);
  111. fflush(stdout);
  112. create_thread(recv_response, arg, NULL, NULL);
  113. }
  114. }
  115.  
  116. SPIDER_LOG(SPIDER_LEVEL_DEBUG, "Task done!");
  117. close(g_epfd);
  118. return ;
  119. }

本项目主要进行网页的抓取,上述为主控制模块

  1. while ((ch = getopt(argc, (char* const*)argv, "vhd")) != -1) {
  2.  
  3. 主要作用为命令行参数的解析,根据命令行参数我们判断是一些额外输出信息和以什么方式进行(ps:守护进成)
  4.  
  1. 24 g_conf = initconfig();
  2. 25 loadconfig(g_conf);
  3.  
  4. 进行初始化配置,对log配置进行加载,
    log配置包含了一些抓取深度,种子,动态库路径等等之类的信息
    下面主要是一些需要抓取前加载的配置文件
  1. cur_thread_num.
  2. max_job_num=
  3. seeds=http://www.imeiding.com
  4. logfile=spiderq.log
  5.  
  6. # Set the level to log. The probable values list as follow:
  7. # DEBUG
  8. # INFO
  9. # WARN
  10. # ERROR
  11. # CRIT
  12. log_level=
  13.  
  14. max_depth=
  15.  
  16. module_path=/etc/spider/modules/
  17.  
  18. load_module=savehtml
  19. load_module=saveimage
  20. load_module=maxdepth
  21. load_module=domainlimit
  22. load_module=headerfilter
  23.  
  24. # specify which type of resource we accept. Each one a line.
  25. # text/html is accepted default
  26. accept_types=image/jpeg
  1. 我们将动态库都存在vector里面,以便后续使用
    但是在读取配置文件的时候我们不要忘记字符串的处理,比如,空行,注释行#,空格,=划分等等问题
  2.  
  3. 接下来设置守护进程,以便使任务脱离终端控制,
  4.  
  5. 创建线程,通过libevent进行dns解析,,开启epoll任务,向epoll中注册事件,模式为ET模式,不断的等待内核中epoll事件的触发并进行处理
  6.  
  7. 通过开启线程进行http请求,手写http头部,进行发送给server端一个http请求报文

http协议请求页面时的流程:

1、 输入网址

2、 向DNS发送解析请求

3、 DNS返回给我们一个对应的IP地址

4、 通过IP地址向资源所在的主机发送请求

5、 如果资源存在,主机返回200状态,同时返回数据部分

6、 本地http客户端(一般来说是浏览器)接收数据

7、 得到资源

  1. 得到http接受报文的时候,对http接收报文进行解析,解析内部的url并放入队列中,并对http接收报文进行持久化操作

linux c++爬虫(一)的更多相关文章

  1. Linux shell爬虫实现树洞网自动回复Robot

    奇怪的赞数 人生在世,不如意事十之八九,可与言者无二三人.幸好我们生在互联网时代,现实中找不到可以倾诉的人还可以在网络上寻找发情绪宣泄口,树洞这类产品就是提供一个让人在网络上匿名倾诉的平台. 我是偶然 ...

  2. Linux 驱动开发

    linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...

  3. 微信小程序开发 [00] 写在前面的话,疯狂唠唠

    我总是喜欢在写东西之前唠唠嗑,按照惯例会在博文的开篇写这么一段"写在前面的话",这次却为了这个唠嗑单独开了一篇文,大概预想着要胡说八道的话有点多. 前段时间突然对小程序来了兴趣,说 ...

  4. Shell脚本日志关键字监控+告警

    最近小张的爬虫程序越来越多,可当爬虫程序报错,不能及时的发现,从而造成某些重要信息不能及时获取的问题,更有甚者,遭到领导的批评.于是就在想有没有一种方法,当爬取信息报错的时候,可以通过邮件或者短信的方 ...

  5. 在linux下python爬虫进程发生异常时自动重启直至正常结束的方法

    之前在做爬虫的时候遇到一种情况,当网络情况不太好的时候,爬虫爬到的链接在urlopen时会因为无法正常连接而报URLError或者timeout的错误导致陈序报错而终止:但是这些错误在重新运行陈序后能 ...

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

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

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

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

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

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

  9. Linux 安装python爬虫框架 scrapy

    Linux 安装python爬虫框架 scrapy http://scrapy.org/ Scrapy是python最好用的一个爬虫框架.要求: python2.7.x. 1. Ubuntu14.04 ...

随机推荐

  1. Linux常用命令整理

    1.常用命令:cd 进入 ls(list)查看当前目录下的文件 pwd 查看目录的路径 who an i 查看当前用户 clear 清除屏幕   2.绝对路径:从根目录开始\ 相对路径:上一层.下一层 ...

  2. get你想象不到的技能

    1.取消选取.防止复制 <body selectStart="return false"> </body> 2.不允许粘贴 <body onpaste ...

  3. JVM年轻代、年老代、永久代

    年轻代: HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫From和To),每次新创建对象时,都会分配到Eden区,当Eden区没有足够的空间进行分配时,虚拟 ...

  4. swust oj(0088)表达式的转换

    表达式的转换(0088) Time limit(ms): 5000 Memory limit(kb): 65535 Submission: 435 Accepted: 93 Accepted 16级卓 ...

  5. hadoop、Storm该选哪一个

    如果hadoop.Storm还感觉混要,那么此篇文章将帮助你把他们完全区分 可以带着下面问题来阅读本文章: 1.hadoop.Storm各是什么运算 2.Storm为什么被称之为流式计算系统 3.ha ...

  6. 间谍网络——tarjan求SCC

    洛谷传送门 看着这道题给人感觉就是tarjan求SCC,然而还得判断是否能控制全部间谍,这就得先从可以贿赂的点dfs一遍. 如果没有全部被标记了,就输出NO,再从没被标记的点里找最小的标号. 如果全被 ...

  7. 使用Maven构建SSH

    本人自己进行的SSH整合,中间遇到不少问题,特此做些总结,仅供参考. 项目环境: struts-2.3.31 + spring-4.3.7 + hibernate-4.2.21 + maven-3.3 ...

  8. APP自识别安卓苹果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. .NET的JSON格式数据的三种转换方式

    说明: 1..Net进行JSON格式的数据传递的时候,势必用到序列化和反序列化对象,总共有三种方式可是在.NET中实现序列化和反序列化的需求. 2.操作JSON的速度是:Json.net > M ...

  10. ASP.NET MVC 常用扩展点:过滤器、模型绑定等

    一.过滤器(Filter) ASP.NET MVC中的每一个请求,都会分配给对应Controller(以下简称“控制器”)下的特定Action(以下简称“方法”)处理,正常情况下直接在方法里写代码就可 ...