Ruby:多线程队列(Queue)下载博客文章到本地
Ruby:多线程下载博客文章到本地的完整代码
#encoding:utf-8
require 'net/http'
require 'thread'
require 'open-uri'
require 'nokogiri'
require 'date' $queue = Queue.new
#文章列表页数
page_nums = 8
page_nums.times do |num|
$queue.push("http://www.cnblogs.com/hongfei/default.html?page="+num.to_s)
end threads = []
#获取网页源码
def get_html(url)
html = ""
open(url) do |f|
html = f.read
end
return html
end def fetch_links(html)
doc = Nokogiri::HTML(html)
#提取文章链接
doc.xpath('//div[@class="postTitle"]/a').each do |link|
href = link['href'].to_s
if href.include?"html"
#add work to the queue
$queue.push(link['href'])
end
end
end def save_to(save_to,content)
f = File.new("./"+save_to+".html","w+")
f.write(content)
f.close()
end #程序开始的时间
$total_time_begin = Time.now.to_i #开辟的线程数
threadNums = 10
threadNums.times do
threads<<Thread.new do
until $queue.empty?
url = $queue.pop(true) rescue nil
html = get_html(url)
fetch_links(html)
if !url.include?"?page"
title = Nokogiri::HTML(html).css('title').text
puts "["+ Time.now.strftime("%H:%M:%S") + "]「" + title + "」" + url
save_to("pages/" + title.gsub(/\//,""),html) if url.include?".html"
end
end
end
end
threads.each{|t| t.join} #程序结束的时间
$total_time_end = Time.now.to_i
puts "线程数:" + threadNums.to_s
puts "执行时间:" + ($total_time_end - $total_time_begin).to_s + "秒"
多线程部分讲解
$queue = Queue.new
#文章列表页数
page_nums = 8
page_nums.times do |num|
$queue.push("http://www.cnblogs.com/hongfei/default.html?page="+num.to_s)
end
首先声明一个Queue队列,然后往队列中添加文章列表页,以便后面可以从这些列表页中提取文章链接,另外queue声明成全局变量($),以便在函数中也可以访问到
我的曾是土木人博客文章列表总共有8页,所以需要实现给page_nums赋值为8
#开辟的线程数
threadNums = 10
threadNums.times do
threads<<Thread.new do
until $queue.empty?
url = $queue.pop(true) rescue nil
html = get_html(url)
fetch_links(html)
if !url.include?"?page"
title = Nokogiri::HTML(html).css('title').text
puts "["+ Time.now.strftime("%H:%M:%S") + "]「" + title + "」" + url
save_to("pages/" + title.gsub(/\//,""),html) if url.include?".html"
end
end
end
end
threads.each{|t| t.join}
通过Thread.new来创建线程
创建线程后,会进入until $queue.empty?循环,直到任务队列为空(即:没有要采集的网址了)
开辟的线程,每次都会从任务队列(queue)取到一个url,并通过get_html函数获取网页源码
由于任务队列中的url有分页url和文章url两种,所以要进行区分。
如果是分页url(url中含有“?page”),就直接提取文章链接。
如果是文章url,就保存到本地(save_to(),文件名为文章title)
在循环体外,创建线程完毕后,需要将创建的线程执行Thread#join方法,以便让主线程等待,
直到所有的线程执行完毕才结束主线程
代码执行时间统计
#程序开始的时间
$total_time_begin = Time.now.to_i
#执行过程 #程序结束的时间
$total_time_end = Time.now.to_i
puts "执行时间:" + ($total_time_end - $total_time_begin).to_s + "秒"
TIme模块的#now方法可以获取当前时间,然后使用to_i,可以将当前时间转换成从1970年1月1日00:00:00 UTC开始所经过的秒数。
获取网页源码
#获取网页源码
def get_html(url)
html = ""
open(url) do |f|
html = f.read
end
return html
end
ruby中,获取网页的方法用Net::HTTP模块和OpenURI模块。OpenURI模块最简单,可以直径将指定网页当成普通文件一样进行操作。
执行结果:使用多线程采集130多篇文章,耗时15秒(单线程:47s左右)

推荐阅读:
作 者:曾是土木人(http://www.cnblogs.com/hongfei)
原文地址:http://www.cnblogs.com/hongfei/p/3696392.html
Ruby:多线程队列(Queue)下载博客文章到本地的更多相关文章
- CSDN博客文章的备份及导出电子书CHM
需要用到的工具集合下载:http://download.csdn.net/source/2881423 在CSDN.百度等写博客文章的应该很多,很多时候担心服务器有一天突然挂了,或者担心自己的号被封了 ...
- 年度十佳 DevOps 博客文章(后篇)
如果说 15 年你还没有将 DevOps 真正应用起来,16 年再不实践也未免太落伍了.在上篇文章中我们了解到 15 年十佳 DevOps 博客文章的第 6-10 名,有没有哪一篇抓住了您的眼球,让您 ...
- [Python学习] 简单网络爬虫抓取博客文章及思想介绍
前面一直强调Python运用到网络爬虫方面很有效,这篇文章也是结合学习的Python视频知识及我研究生数据挖掘方向的知识.从而简介下Python是怎样爬去网络数据的,文章知识很easy ...
- 一文搞定scrapy爬取众多知名技术博客文章保存到本地数据库,包含:cnblog、csdn、51cto、itpub、jobbole、oschina等
本文旨在通过爬取一系列博客网站技术文章的实践,介绍一下scrapy这个python语言中强大的整站爬虫框架的使用.各位童鞋可不要用来干坏事哦,这些技术博客平台也是为了让我们大家更方便的交流.学习.提高 ...
- 利用爬虫将Yuan先生的博客文章爬取下来
由于一次巧遇,我阅读了Yuan先生的一篇博客文章,感觉从Yuan先生得博客学到很多东西,很喜欢他得文章.于是我就关注了他,并且想阅读更多出自他手笔得博客文章,无奈,可能Yuan先生不想公开自己得博客吧 ...
- 使用IntelliJ IDEA开发SpringMVC网站(五)博客文章管理
原文:使用IntelliJ IDEA开发SpringMVC网站(五)博客文章管理 摘要 通过对博客文章的管理,实现外键操作. 目录[-] 八.博客文章管理 1.查看文章 2.添加博客 3 ...
- HelloDjango 第 08 篇:开发博客文章详情页
作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 首页展示的是所有文章的列表,当用户看到感兴趣的文章时,他点击文章的标题或者继续阅读的按 ...
- 利用爬虫爬取指定用户的CSDN博客文章转为md格式,目的是完成博客迁移博文到Hexo等静态博客
文章目录 功能 爬取的方式: 设置生成的md文件命名规则: 设置md文件的头部信息 是否显示csdn中的锚点"文章目录"字样,以及下面具体的锚点 默认false(因为csdn中是集 ...
- SQL Sever 博客文章目录(2016-07-06更新)
SQL Server方面的博客文章也陆陆续续的写了不少了,顺便也将这些知识点整理.归纳一下下.方便自己和他人查看. MS SQL 数据类型 三大数据库对比研究系列--数据类型 MS SQL 表和视图 ...
随机推荐
- c#中委托与事件
参考:http://www.tracefact.net/tech/009.html 张子阳:http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/9 ...
- HDU 5656 CA Loves GCD (容斥)
题意:给定一个数组,每次他会从中选出若干个(至少一个数),求出所有数的GCD然后放回去,为了使自己不会无聊,会把每种不同的选法都选一遍,想知道他得到的所有GCD的和是多少. 析:枚举gcd,然后求每个 ...
- asp.net DataReader DataTable 使用反射给给实体赋值
asp.net 使用反射给给实体赋值 实体类继承此基类 using System.Reflection; using System.Data.SqlClient; using System.Data; ...
- 视图,sql注入问题,事物,存储过程
视图:本质是一张虚拟的表数据来自select语句用途是保障原表安全 功能1:隐藏部分数据,开放指定数据功能2:因为视图可以将查询结果保存的特性,我们可以用视图来达到减少书写sql语句的功能 例如:se ...
- Android Studio自定义组合控件
在Android的开发中,为了能够服用代码,会把有一定共有特点的控件组合在一起定义成一个自定义组合控件. 本文就详细讲述这一过程.虽然这样的View的组合有一个粒度的问题.粒度太大了无法复用,粒度太小 ...
- css 特殊使用技巧
1 border颜色设置 border-color: transparent black black black; 分别设置四条边框的颜色 上边transparent 透明无色 2 阴影 t ...
- java基础-day18
第07天 集合 今日内容介绍 u HashSet集合 u HashMap集合 第1章 HashSet集合 1.1 Set接口的特点 Set体系的集合: A:存入集合的顺序和取出集合的顺序不一 ...
- java的并发和多线程
本文主要讲解Java并发相关的内容,包括锁.信号量.堵塞队列.线程池等主要内容. 并发的优点和缺点 在讲述怎么利用多线程的情况下,我们先看一下采用多线程并发的优缺点. 优点 提高资源利用率 如读取一个 ...
- 利用Delphi编程控制摄像头(图)
你的电脑有没有摄像头?看到别人用QQ玩视屏你会不会去想怎么实现的?这里介绍使用DELPHI使用MS的 AVICAP32.DLL就可轻松的实现对摄像头编程,如果再加上你的网络编程水平,实现一个视屏聊天就 ...
- 运行批处理文件怎么不显示DOS命令窗口
运行批处理文件怎么不显示DOS命令窗口 BAT没法不显示DOS窗口.你可以考虑用脚本保持以下到文本文件,重命名为AutoUp_ddyy.vbs set WshShell = WScript.Cre ...