免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9241 | 回复: 13
打印 上一主题 下一主题

这个可是效率最高的爬虫 [复制链接]

论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-09-29 14:10 |只看该作者 |倒序浏览
取一个这么有吸引力的标题 主要为了介绍AE和Coro家族,爬虫只是一个小例子。

不完善的地方是URL处理函数,需要考虑的比较全面,我这里简单化了。

将代码保持到test.pl里,执行perl test.pl 'http://bbs.chinaunix.com',就开始抓整站了。
  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;

  4. use Coro;
  5. use AnyEvent::HTTP;
  6. use BerkeleyDB;


  7. # 参数设置
  8. my $limit = 10; # 异步抓取数量


  9. # 初始化数据库
  10. my $filename = "URLs.db";
  11. tie my %url, 'BerkeleyDB::Btree',
  12.     -Filename => $filename,
  13.     -Flags    => DB_CREATE
  14.     or die "Cannot open $filename: $! $BerkeleyDB::Error\n";

  15. $filename = "Queue.db";
  16. tie my @queue, 'BerkeleyDB::Recno',
  17.     -Filename => $filename,
  18.     -Flags    => DB_CREATE
  19.     or die "Cannot open $filename: $! $BerkeleyDB::Error\n";


  20. # 初始化进度条
  21. my $total;
  22. my $done;
  23. if (exists $ARGV[0]){
  24.     push @queue, $ARGV[0];
  25.     $url{$ARGV[0]} = 1;
  26.     $total         = 1;
  27.     $done          = 0;
  28. }else {exit 0};

  29. # 间隔一段时间报一次进度
  30. $| = 1;
  31. my $progress = AnyEvent->timer (
  32.     after => 0,
  33.     interval => 1,
  34.     cb    => sub {
  35.         print "*当前进度:$done/$total(完成/总量)\r";
  36.     },
  37. );


  38. # 异步HTTP请求
  39. my $sem = new Coro::Semaphore $limit;
  40. my $sig = new Coro::Signal;
  41. $Coro::POOL_SIZE            = $limit;

  42. while (1){
  43.     if(my $url = pop @queue){     # 列队请求
  44.         $sem->down;
  45.         async_pool {
  46.             my $url = shift;
  47.             http_get $url, Coro::rouse_cb;

  48.             my @res = Coro::rouse_wait;
  49.             my $urls = &URL($url,\$res[0]);

  50.             foreach (@$urls){
  51.                 if (not exists $url{$_}){
  52.                     push @queue, $_;
  53.                     $url{$_} = 1;
  54.                     $total++;
  55.                 }
  56.             }

  57.             $done++;
  58.             $sem->up;
  59.             $sig->send;
  60.         } $url;
  61.     }elsif($sem->count < $limit){ # 等待剩余进程返回
  62.         $sig->wait;
  63.     }else{                        # 全部剩余进程返回,结束循环
  64.         last;
  65.     }
  66. }

  67. undef $progress;
  68. print "\n抓取完成:完成$done/总量$total\n";

  69. # 关闭数据库连接
  70. untie %url;
  71. untie @queue;

  72. sub URL{
  73.     my $base = shift;
  74.     my $HTML = shift;
  75.     #scheme://domain:port/path?query_string#fragment_id
  76.     my $sdp;
  77.     if ($base =~ m#^(\w+://[^/]+)/?#){
  78.         $sdp = $1;
  79.     }
  80.     my $sdpp;
  81.     if ($base =~ m#^(\w+://.+)/[^/]?#){
  82.         $sdpp = $1 . '/';
  83.     }else {$sdpp = $sdp . '/'}

  84.     my @urls;
  85.     while ($HTML =~ /<a\b([^>]+)>/ig){
  86.         if ($1 =~ /\bhref\s*=\s*(?:"([^"]*)"|'([^']*)'|([^'">\s]+))/i){
  87.             my $url = $+;
  88.             next if (
  89.                      $url =~ /^#/             ||
  90.                      $url =~ /^javascript:;/i ||
  91.                      $url =~ /^mailto:/i);

  92.             if ($url =~ m#^http://#i && $url =~ /$sdp/){
  93.                 push @urls, $url;
  94.             }elsif ($url =~ m#^/[^/]#){
  95.                 push @urls, $sdp . $url;
  96.             }elsif ($url =~ /^\.[^.]/){
  97.                 push @urls, $sdpp . substr $url, 2;
  98.             }elsif ($url =~ /^\w/){
  99.                 push @urls, $sdpp . $url;
  100.             }#else处理异常
  101.         }
  102.     }

  103.     return \@urls;
  104. }
复制代码

论坛徽章:
8
技术图书徽章
日期:2013-08-22 11:21:28未羊
日期:2015-01-19 22:22:25巳蛇
日期:2014-08-11 16:53:08子鼠
日期:2014-05-29 09:04:44摩羯座
日期:2014-04-11 14:15:07丑牛
日期:2014-01-24 12:41:28金牛座
日期:2013-11-21 17:38:28射手座
日期:2015-01-21 08:50:32
2 [报告]
发表于 2014-09-29 14:29 |只看该作者
楼主,你知道py(安)thon(利)麽。。。。

论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
3 [报告]
发表于 2014-09-29 14:36 |只看该作者
欢迎python的朋友交流,写个比较下?

论坛徽章:
32
处女座
日期:2013-11-20 23:41:20双子座
日期:2014-06-11 17:20:43戌狗
日期:2014-06-16 11:05:00处女座
日期:2014-07-22 17:30:47狮子座
日期:2014-07-28 15:38:17金牛座
日期:2014-08-05 16:34:01亥猪
日期:2014-08-18 13:34:25白羊座
日期:2014-09-02 15:03:55金牛座
日期:2014-11-10 10:23:58处女座
日期:2014-12-02 09:17:52程序设计版块每日发帖之星
日期:2015-06-16 22:20:002015亚冠之塔什干火车头
日期:2015-06-20 23:28:22
4 [报告]
发表于 2014-09-29 19:49 |只看该作者
perl也可以写爬虫啊?涨姿势了~{:3_193:}

论坛徽章:
0
5 [报告]
发表于 2014-09-29 23:21 |只看该作者
效率最高。。。。

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
6 [报告]
发表于 2014-09-30 09:17 |只看该作者
支持LZ.
@墨迹哥 来交流一下

论坛徽章:
0
7 [报告]
发表于 2014-09-30 15:11 |只看该作者
Windows下如何创建BerkeleyDB环境,尝试了一下没成功!

论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
8 [报告]
发表于 2014-09-30 17:25 |只看该作者
不用BerkeleyDB也可以的,很简单,将初始化数据库的代码改成my两个同名的变量就行了。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2014-09-30 19:19 |只看该作者
本帖最后由 py 于 2014-12-13 15:34 编辑

终于看到有人写Coro的爬虫了。标题没写错,楼主可以发个链接到那个叫什么python的板块去

论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
10 [报告]
发表于 2014-09-30 19:56 来自手机 |只看该作者
Coro::Channel我没有思路呀,你说下模型我参考下或许可以写出来。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP