免费注册 查看新帖 |

Chinaunix

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

第一个多线程抓取程序,遭遇夭折,请高手诊断一下,谢谢! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-07-20 12:07 |只看该作者 |倒序浏览
本帖最后由 sx98083714 于 2010-07-21 10:47 编辑

#!/usr/bin/perl
use strict;
use utf8;
use Encode;
use LWP::UserAgent;
use threads;
use Thread::Semaphore;
use threads::shared;

binmode(STDOUT,":encoding(utf8");

my %mail_list;   

#注:从mail_list.txt文件中读取已获取到邮件地址的用户列表

my %user_list;

#注:从user_list.txt文件中读取所有用户列表(可能包含邮件地址已经获取到的用户)

my $max_thread = 4;

my $semaphore=Thread::Semaphore->new();

share(%mail_list);
share(%user_list);

#将所有用户列表放入%user_list散列

open(UL,"user_list.txt");
while(<UL>){
        chomp($_);
        my ($user,$id)=split("\t",$_);
        $user_list{$id}=$user;
}
close(UL);

#将所有已经获取了邮件地址的用户放入%mail_list散列

open(FH,"<mail_list.txt");
while(<FH>){
        chomp($_);
        my ($user,$id,$mail)=split("\t",$_);
        $mail_list{$id}=$user;
}
close(FH);

open(ML,">>mail_list.txt");

sub ths_submit{
        my($start,$stop)=@_;
        my $i=0;
        while(my ($id,$user)=each %user_list){
                $i++;
                if($i>$start and $i<=$stop){
                        if(defined $mail_list{$id}){  #注:如果当前用户已经在%mail_list散列中,表示该用户邮件已获取过,不用再重复获取
                                {
                                        lock(%user_list);
                                        delete $user_list{$id};
                                }
                        }else{
                                my $rst=&get_mail($user,$id);
                                if($rst==0){   #注:返回0表示获取邮件失败,重新放回数组
                                        {
                                                lock(%user_list);
                                                $user_list{$id}=$user;
                                                next;
                                        }
                                }
                        }
                }else{
                        next;
                }
        }
        # 释放一个信号量,表示一个线程运行结束
        $semaphore->up( );        
}

foreach my $i(1..$max_thread){
        my $start=$i*10000-10000;
        my $stop=$start+10000;
        my $i = threads->create( \&ths_submit, $start,$stop );
        $i->detach();
}

Wait2Quit( );

sub Wait2Quit{

        print "Waiting to quit...\n";

        my $num = 0;

        while( $num < $max_thread ){
               
                # 尝试获取信号量,当能够获取到最大线程数个信号量时,表示所有线程都结束了
               
                $semaphore->down( );
                $num ++;
                print "$num thread quit.\n";               
        }
        print "All $max_thread thread quit.\n";
}

sub get_mail{
        chomp(my $user=shift);
        chomp(my $id=shift);
        $user=decode('utf8',$user);
        my $u=$user;
        print "开始抓取用户: $user 的邮件 ...... \n";
        $user=encode('gbk',$user);
        my $browser=LWP::UserAgent->new();
        $browser->proxy('http','http://221.130.17.50:80');
        $browser->timeout(10000);
        my $url="http://xxxx";
        my $response=$browser->post($url,
        [
        'username1'=>$user,
        ],
        'User-Agent'=>'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.12) Gecko/2009072711 CentOS/3.0.12-1.el5.centos Firefox/3.0.12',
        'Accept'=>'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language'=>'en-us,en;q=0.5',
        'Accept-Encoding'=>'gzip,deflate',
        'Accept-Charset'=>'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
        'Cache-Control'=>'max-age=0',
        );
        print "错误的返回类型 -- ", $response->content_type unless $response->content_type eq 'text/html';
        if($response->is_success){
                my $content=$response->content;
                $content=decode('gbk',$content);
                #$content=~/.*?请尽快到<(.*)>检查邮件并操作.*/;
                #my $mail=$1;
                if ($content=~/.*?请尽快到<(.*)>检查邮件并操作.*/){
                        $mail_list{$id}=$user;
                        print "写入用户$u 的邮件到文件,完成\n";
                        $u=encode('utf8',$u);
                        print ML "$u\t$id\t$1\n";
                        return 1;
                }else{
                        if($content=~/.*?找不到您输入的用户名.*/){
                                print "该用户".$u."不存在\n";
                        }elsif($content=~/.*?本论坛设置了.*/){
                                print "用户".$u."在一小时内只能提交一次\n";
                        }else{
                                print "获取用户 $u 出错\n";
                        }
                        return 0;
                }
        }else{
                print "获取当前用户邮件地址失败,失败原因:".$response->status_line;
                return 0;
        }

}

程序运行后,报错:

Segmentation fault

好像是数组越界什么的,这个程序感觉还是蛮有代表意义的,如果能解决,对我自己对初学者应该都有一定意义吧,希望高手不吝赐教了,谢谢!

由于本人是第一尝试写多线程的程序,没会经验,其中部分思路借鉴了云老大的思路,这里注明一下。原文地址在:http://www.icylife.net/yunshu/show.php?id=617

论坛徽章:
0
2 [报告]
发表于 2010-07-20 13:05 |只看该作者
先顶一下了,等着高手现身了!

论坛徽章:
0
3 [报告]
发表于 2010-07-20 15:40 |只看该作者
再顶下。怎么就没人呢?

论坛徽章:
0
4 [报告]
发表于 2010-07-20 15:42 |只看该作者

论坛徽章:
0
5 [报告]
发表于 2010-07-20 16:11 |只看该作者
非常感谢 黑色阳光_cu 的回复!谢谢!

那个贴子我一定会花点时间好好学习下的,只是我现在这个能帮我看一下研究问题在哪吗?非常抱歉得寸进尺了!主要是学习消化那个需要时间,我想先把我这个问题弄明白才好,这个毕竟自己弄的,思路上更清楚点。呵呵。

论坛徽章:
0
6 [报告]
发表于 2010-07-20 17:31 |只看该作者
快下班了,赶紧再顶一下。

论坛徽章:
0
7 [报告]
发表于 2010-07-20 23:57 |只看该作者
漫漫长夜,无人问津,郁闷ing。

论坛徽章:
0
8 [报告]
发表于 2010-07-21 09:30 |只看该作者
看多回少,郁闷。

论坛徽章:
0
9 [报告]
发表于 2010-07-21 10:37 |只看该作者
看到那么多笑脸符在代码中,我想帮忙分析一下,但看得我头都大了,只好放弃

论坛徽章:
0
10 [报告]
发表于 2010-07-21 10:49 |只看该作者
不好意思,楼上的兄弟,没太多经验,提交后这样,我还以为特殊字符过滤了,所以那样显示。

我刚编辑了下,选上“所见即所得”再编辑下就可以了。报歉,以前没留意。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP