`
bubble
  • 浏览: 146007 次
  • 性别: Icon_minigender_1
  • 来自: 辽宁
社区版块
存档分类
最新评论

用ruby写的一个网络爬虫程序

 
阅读更多
这个程序写的很简单,刚接触ruby第二天写的,主要完成的功能是到斯坦福大学的网站上去收集email地址,  ,默认是10个线程,策略是广度优先,$debug=true时开启调试信息。附件中包含代码和批处理文件。

运行命令为:
ruby Crawl.rb 2 1000 http://www-cs.stanford.edu/People
其中参数:2->max_depth, 1000->max_pages, http://www-cs.stanford.edu/People->URL
运行结果输出为文档文件emails_md[max_depth]_mp[max_pages]_[URL].txt

居然删不了帖子,那我就拿掉吧,剩着再遭隐藏,呵呵
还是贴回来吧,省着自己想找都找不到,哈哈

require 'open-uri'
require 'thread'
# run it like this :
# ruby Crawl.rb 2 1000 http://www-cs.stanford.edu/People
# regexp
$link_regexp = /href\=\"[^\"]*\"/
$email_regexp_1 = /mailto\:[^\@]*\@[^\"]*[\"]/	#mailto:xx@xxxx"
$email_regexp_2 = /[\>][^\<]*\@[^\>]*[\<]/	#>xx@xx<
$before_at = /[a-zA-Z0-9]+[_?a-zA-Z0-9]+/
$after_at = /[a-zA-Z]+[-?a-zA-Z]*\.+[a-zA-Z]+/
$email_regexp=/#{$before_at}\@#{$after_at}/	#xx@xx.xx

#ARGV 
if ARGV==nil||ARGV.length<3
	puts '-- Command --'
	puts 'ruby Crawl.rb 2 1000 http://www-cs.stanford.edu/People'
	puts 'help: 2->max_depth, 1000->max_pages, http://www-cs.stanford.edu/People->url'
	exit(0)
end
$url=ARGV[2]
$max_depth=ARGV[0].to_i
$max_pages=ARGV[1].to_i
$fname='emails_md'+String($max_depth)+'_mp'+String($max_pages)+'_'+$url.gsub(/[\/\:]/,'_')+'.txt'
$fname_links='links_md'+String($max_depth)+'_mp'+String($max_pages)+'_'+$url.gsub(/[\/\:]/,'_')+'.txt'
$thread_num=10
$debug=true

$links_stack=[]		#fifo #[[depth1,link1],[depth2,link2],[depth3,link3],...]
$links_crawled=[]	#[url1,url2,url3,...] 
$emails=[]		#[email1,email2,email3,...]

class Crawl
	def initialize url,depth
		@url=url
		while @url[-1,1]=='/'
			@url=@url.slice(0,@url.length-1) 
		end
		@depth=depth
		begin
		@html=open(@url).read
		rescue
		@html=''
		end
	end
	def get_links
		@html.scan($link_regexp) do |match| 
			u=Util.format_url(match,@url)
			if !(u==nil)&&!$links_crawled.include?(match)&&$links_stack.rassoc(match)==nil
				$links_stack.push [@depth,u]
			end
		end
	end
	def get_emails
		@html.scan($email_regexp_1) do |match| 
			match=Util.format_email(match)
			if match!=nil&&!$emails.include?(match)
				$emails.push match
				msg= match+', '+@url
				puts msg
				Util.write($fname,msg+"\r\n")
			end
		end
		@html.scan($email_regexp_2) do |match| 
			match=Util.format_email(match)
			if match!=nil&&!$emails.include?(match)
				$emails.push match
				msg= match+', '+@url
				puts msg
				Util.write($fname,msg+"\r\n")
			end
		end
	end
end

class Util
	# format url
	def Util.format_url url,f_url
		# remove 'www-'
		f_url=f_url.gsub(/www\-/, '')
		url=url[6,url.length-7]
		# exclude css & js & '#'(eg http://www-cs.stanford.edu/People/faculty#Regular%20Faculty)...
		if Util.exclude(url)==nil||url.include?('#')
			return nil
		end
		# full path
		if url[0,4]!='http'
			while url.index('/')==0
				url=url.slice(1,url.length-1) 
			end
			url=f_url+'/'+url
		end
		return url
	end
	# format email
	def Util.format_email email
		email=email.delete('>').delete('<').delete('mailto:').delete('"').strip
		if String($email_regexp.match(email))== email
			return email.downcase
		else
			return nil
		end
	end
	# write msg to file
	def Util.write fname,msg
		file=File.new(fname,'a')
		file<<msg
		file.close()
	end
	# exclude css & js...
	def Util.exclude str
		ex=['css','js','pdf','jpg']
		ex.each do |e|
			index=e.length+1
			if str.length>index && str[-index,index]=='.'+e
				return nil
			end
		end
		return str
	end
end
$count=1
0.upto($max_depth) do |i|
	if $debug
		puts '~~depth->'+String(i)
	end	
	if i==0
		c=Crawl.new($url,i+1)
		c.get_links
		c.get_emails
		$links_crawled.push [i,$url]
	end
	#breadth first 
	while $links_stack.length!=0
		if $debug
			puts '~~count->'+String($count)+',stack->'+String($links_stack.length)+',crawled->'+String($links_crawled.length)+',total->'+String($links_crawled.length+$links_stack.length)
			$count=$count+1
		end		
		#Thread.abort_on_exception = true
		threads = []
		if $links_stack.length/$thread_num>=1
			ts=$thread_num
		else 
			ts=$links_stack.length%$thread_num
		end
		ts.times { |i|
			threads << Thread.new(i) {
			Mutex.new.synchronize {
				if ($links_crawled.length+$links_stack.length)<=$max_pages&&i!=$max_depth
					link=$links_stack.shift		#fifo
					if  link[0]==i+1
						#read links & emails from pages in stack
						c=Crawl.new(link[1],i+2)
						c.get_links
						c.get_emails
						$links_crawled.push link[1]
					else 
						break
					end
				else
					#only read emails from pages in stack
					link=$links_stack.shift
					c=Crawl.new(link[1],i+2)
					c.get_emails
					$links_crawled.push link[1]
				end
			}
			}
		}
		threads.each{|t|t.join}
	end
end
分享到:
评论
7 楼 bubble 2009-12-13  
我准备把帖子删掉算了,心寒啊。
qiaoakai 写道
Very Good!!!虽然,我没看懂!!

呵呵,写的太烂是不是?
wangfsec 写道
怎么做到广度优先的?

用的队列。
hc_face 写道
我还不会用隐藏贴,但是我在学ruby,敬佩楼主的贡献精神,学习!!

多亏你不会用隐藏帖,要不又多一个,汗!
tianyuzhu 写道
原来如此,

这位大哥受到啥启发了?
6 楼 tianyuzhu 2009-12-12  
原来如此,
5 楼 hc_face 2009-12-12  
我还不会用隐藏贴,但是我在学ruby,敬佩楼主的贡献精神,学习!!
4 楼 wangfsec 2009-12-12  
怎么做到广度优先的?
3 楼 qiaoakai 2009-12-12  
Very Good!!!虽然,我没看懂!!
2 楼 bubble 2009-12-12  
呵呵,有点郁闷居然6个隐藏帖,给点面子不好吗,投个新手帖我还能接受,javaeye玩Ruby的看来都是高手啊
1 楼 wangxin0072000 2009-12-11  
$link_regexp = /href\=\"[^\"]*(\")$/  

相关推荐

    Python开发简单爬虫视频教程.rar

    众所周知,每个网页通常包含其他网页的入口,网络爬虫则通过一个网址依次进入其他网址获取所需内容。 爬虫可以作为通用搜索引擎网页收集器和垂直搜索引擎。爬虫是搜索引擎的第一步也是最容易的一步。C,C++适合通用...

    JAVA上百实例源码以及开源项目源代码

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    Java资源包01

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    spidr_test:用于端到端测试的网络爬虫

    将此行添加到应用程序的 Gemfile 中: gem 'spidr_test' 然后执行: $ bundle 或者自己安装: $ gem install spidr_test 用法 TODO:在这里写使用说明 发展 签出 repo 后,运行bin/setup来安装依赖项。 然后...

    java开源包1

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包11

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包2

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包3

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包6

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包5

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包10

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包4

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包8

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包7

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包9

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包101

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    JAVA上百实例源码以及开源项目

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    若干源程序资料12.rar

    2012-06-11 21:06 387,499 c语言写的一个多任务内核.rar 2012-06-11 21:15 6,669,174 C语言常用算法集(人手一份).pdf 2012-06-11 21:44 2,279 C语言编一个程序完成64位数据(无符号)的加法,减法运算.txt 2012-06-...

    Python-Websockify是一个WebSocket至TCP的代理桥梁

    Websockify是一个WebSocket至TCP的代理/桥梁。实现让让浏览器可以连接至任何应用程序/服务器/服务。采用Python, C, Node.js 和Ruby。

Global site tag (gtag.js) - Google Analytics