• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    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
      threadsThread.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
      threadsThread.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左右)

    您可能感兴趣的文章:
    • Ruby中使用mechanize批量下载校内网相册照片
    • ruby实现的一个异步文件下载HttpServer实例
    • 比较不错的关于ruby的电子书下载地址集合
    • windows和linux下Ruby的下载与安装
    • Ruby使用eventmachine为HTTP服务器添加文件下载功能
    上一篇:Ruby中使用mechanize批量下载校内网相册照片
    下一篇:Ruby中用线程实现经典的生产者消费者问题代码实例
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Ruby中使用多线程队列(Queue)实现下载博客文章保存到本地文件 Ruby,中,使用,多,线程,队列,