免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖

下大雪不能出门,在家做了个简单的爬虫demo [复制链接]

论坛徽章:
0
发表于 2009-12-28 20:25 |显示全部楼层
我写Perl从来没做过WEB方面的开发,都是一些帮助自己工作的系统网络方面的。对于线程进程没有仔细测试,不过根据不可靠的经验来看线程还是比进程轻量级。

论坛徽章:
0
发表于 2009-12-28 20:34 |显示全部楼层

回复 #11 撒哈拉里的鱼 的帖子

【OT】你做的工作与俺前一阵做的工作差不多,不过我是指定抓特定网页的内容。
当时说不让用perl搞,于是我用C写,研究了一阵libcurl,觉得不是完全适合自己。
就自己动手写,花了不少时间也没完全搞好(例如返回网页的不同编码问题)。
后来用perl重写了下,几十行就搞好了。scratch computing这块,perl强悍的说~~

论坛徽章:
0
发表于 2010-01-04 16:42 |显示全部楼层
今天给一个同事实际环境应用了,呵呵,所以略微改了一点代码,发出来。主要是加了一个线程互斥。

  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. #use Data::Dumper;
  5. use threads;
  6. use threads::shared;
  7. use Thread::Queue;
  8. use Thread::Semaphore;

  9. use Bloom::Filter;
  10. use URI::URL;
  11. use Web::Scraper;

  12. my $max_threads = 15;
  13. my $base_url = $ARGV[0] || 'http://www.icylife.net';
  14. my $host = URI::URL->new($base_url)->host;

  15. my $queue = Thread::Queue->new( );

  16. my $semaphore = Thread::Semaphore->new( $max_threads );
  17. my $mutex = Thread::Semaphore->new( 1 );

  18. my $filter = shared_clone( Bloom::Filter->new(capacity => 10000, error_rate => 0.0001) );

  19. $queue->enqueue( $base_url );
  20. $filter->add( $base_url );

  21. while( 1 )
  22. {
  23.         # join all threads which can be joined
  24.         #my $joined = 0;
  25.         foreach ( threads->list(threads::joinable) )
  26.         {
  27.                 #$joined ++;
  28.                 $_->join( );
  29.         }
  30.         #print $joined, " joinedn";

  31.         # if there are no url need process.
  32.         my $item = $queue->pending();
  33.         if( $item == 0 )
  34.         {
  35.                 my $active = threads->list(threads::running);
  36.                 # there are no active thread, we finish the job
  37.                 if( $active == 0 )
  38.                 {
  39.                         print "All done!\n";
  40.                         last;
  41.                 }
  42.                 # we will get some more url if there are some active threads, just wait for them
  43.                 else
  44.                 {
  45.                         #print "[MAIN] 0 URL, but $active active threadn";
  46.                         sleep 1;
  47.                         next;
  48.                 }
  49.         }

  50.         # if there are some url need process
  51.         #print "[MAIN] $item URLn";
  52.         $semaphore->down;
  53.         #print "[MAIN]Create thread.n";
  54.         threads->create( \&ProcessUrl );
  55. }

  56. # join all threads which can be joined
  57. foreach ( threads->list() )
  58. {
  59.         $_->join( );
  60. }

  61. sub ProcessUrl
  62. {
  63.         my $scraper = scraper
  64.         {
  65.                 process '//a', 'links[]' => '@href';
  66.         };

  67.         my $res;
  68.         my $link;

  69.         while( my $url = $queue->dequeue_nb() )
  70.         {
  71.                 eval
  72.                 {
  73.                         $res = $scraper->scrape( URI->new($url) )->{'links'};
  74.                 };
  75.                 if( $@ )
  76.                 {
  77.                         warn "$@\n";
  78.                         next;
  79.                 }
  80.                 next if (! defined $res );

  81.                 #print "there are ".scalar(threads->list(threads::running))." threads, ", $queue->pending(), " urls need process.n";

  82.                 foreach( @{$res} )
  83.                 {
  84.                         $link = $_->as_string;
  85.                         $link = URI::URL->new($link, $url);

  86.                         # not http and not https?
  87.                         next if( $link->scheme ne 'http' && $link->scheme ne 'https' );
  88.                         # another domain?
  89.                         next if( $link->host ne $host );

  90.                         $link = $link->abs->as_string;

  91.                         if( $link =~ /(.*?)#(.*)/ )
  92.                         {
  93.                                 $link = $1;
  94.                         }

  95.                         next if( $link =~ /.(jpg|png|bmp|mp3|wma|wmv|gz|zip|rar|iso|pdf)$/i );

  96.                         $mutex->down();
  97.                         if( ! $filter->check($link) )
  98.                         {
  99.                                 print $filter->key_count(), " ", $link, "\n";
  100.                                 $filter->add($link);
  101.                                 $queue->enqueue($link);
  102.                         }
  103.                         $mutex->up();
  104.                         undef $link;
  105.                 }
  106.                 undef $res;
  107.         }
  108.         undef $scraper;
  109.         $semaphore->up( );
  110. }
复制代码

论坛徽章:
0
发表于 2010-01-04 22:15 |显示全部楼层
正好有这方面的需求,学习。

论坛徽章:
0
发表于 2010-01-04 23:39 |显示全部楼层

回复 #8 撒哈拉里的鱼 的帖子

运行了下,不太明白。想了解下,这段代码在干啥?学习下...多谢!

论坛徽章:
0
发表于 2010-02-25 11:07 |显示全部楼层
我写Perl从来没做过WEB方面的开发,都是一些帮助自己工作的系统网络方面的。对于线程进程没有仔细测试,不过 ...
撒哈拉里的鱼 发表于 2009-12-28 20:25



   
操作系统不同,进程跟线程的方式也不同,在windows下面线程是很强悍的,但Linux/Unix下面始终不太好使, 内存泄露得也多

论坛徽章:
0
发表于 2010-02-25 17:15 |显示全部楼层
本帖最后由 greensnow 于 2010-02-25 17:18 编辑

perl不适合做这个,异步的还好说,多线程很惨
不信你开50线程,跑一个小时,看要吃掉多少内存
多进程都比这个好,跑一段时间后可以重新fork,释放下资源
我也用perl写过类似的应用,但结果是用C重写了

论坛徽章:
0
发表于 2010-09-19 16:51 |显示全部楼层
回复 12# 兰花仙子


    孤陋寡闻一下啊,请问scratch computing是什么意思呢,字面看上去是"从头计算"的意思

论坛徽章:
0
发表于 2010-09-20 13:21 |显示全部楼层
学习学习···

论坛徽章:
0
发表于 2012-11-05 11:43 |显示全部楼层
CU里面高手很多。虚心学习,不过现在高人都不怎么出现了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP