ruby 抓取脚本

今天用 httpclient + hpricot 写了个备份我的blog的脚本 , 把图片 和文章都给抓了下来 , 由于没有备案 , 害怕有一天被和谐了 , 所以 还是早点备份一下为好 , 或者 以后自己 买了 VPS , 也好导入数据。

这只是一个简单的脚本 , 100 行左右就搞定了 , 更多的spider ,可以自由发挥 , 感兴趣的可以down下来研究研究 , 只是针对我的blog写的脚本 , 主要就是解析html这里不一样,其它差不多 , 核心代码:

require 'rubygems'
require 'open-uri'
require 'hpricot'
require 'fileutils'
require 'httpclient'
require 'md5'
 
def debug content
  File.open("./#{PREFIX_LOG}spide.log","a+") { |file| file.write("#{content}\t" + DateTime.now(:db).to_s + "\n" ) }
end
 
def blog post
  path = "./#{PREFIX_BLOG}#{post[:title]}.html"
  if !File.exist?(path)
    File.new(path,"w+")
    File.open(path,"a+") do |file|
      file.write(W3C + "\n#{post[:title]}\r" + "#{post[:pub_time]}\n\n" + "#{post[:content]}\n")
    end
  end
end
 
def spide url , page = 10
 
  page.times do |p|
    p = p+1
    next  if page_spided? url , p
    page_urls = page_url url , p  
    page_urls.each do |u|
      next if url_spided? u
      File.open("./#{PREFIX_LOG}url.log","a+") { |f| f.write("spide_url|#{u}\n") }
      post =  spide_detail u
      blog post
    end
 
  end
 
end
 
# 页面里所有的文章连接(title)
def page_url url , p
  urls = Array.new
  url = url + "/page/#{p}"
  File.open("./#{PREFIX_LOG}page.log","a+") { |f| f.write("spide_page|#{p}|#{url}\n") }
  client = HTTPClient.new
  html = client.get_content(url,UA)
  doc = Hpricot(html)
  doc.search("h2[@class=entry-title]>a")  do |a|
    urls << a['href']
  end
 
  urls
end
 
# 解析 HTML
def spide_detail url
  post = Hash.new
  debug "spide #{url}"
  client = HTTPClient.new
  html = client.get_content(url,UA)
  doc = Hpricot(html)
 
  # 文章标题
  title = doc.search("h2[@class=entry-title]").inner_text
  post[:title] = title
 
  #发布时间
  pub_time = doc.search("abbr").inner_text
  post[:pub_time] = pub_time
 
  imgs = Array.new
 
  doc.search("div[@class=entry-content]").search("img").each do |i|
    imgs <<  i['src']
  end
 
  save_image imgs
 
  #内容
  content = doc.search("div[@class=entry-content]").inner_html 
  #   content.gsub!(/src="[a-zA-z]+:\/\/[^\s]*/)
  post[:content] = content 
 
  post
 
end
 
 
def save_image imgs
 
  FileUtils.mkdir './images' unless File.directory?('./images')
 
  imgs.each do |url|
    begin
      uri = URI.parse(url)
      format = uri.path.split(".").last
      img_name = "#{MD5.hexdigest(url)}.#{format}"
 
      if File.exist?("./images/#{img_name}")
        debug "exist #{url}"
        return 
      end
 
      client = HTTPClient.new
      body = client.get_content(url,UA)
      if body
        File.open("./images/#{img_name}","w") { |file| file.write(body) }
      end
 
    rescue => err
      debug err.inspect
      return nil
    end
  end
 
end
 
def page_spided? url , p
  path = "./#{PREFIX_LOG}page.log"
  File.new(path,"w+") unless File.exists?(path)
  File.open(path,"r").each_line do |line|
    if line.index("spide_page|#{p}|#{url}")
      return true
    end
  end
  return false
end
 
def url_spided? url
  path =  "./#{PREFIX_LOG}url.log"
  File.new(path,"w+") unless File.exists?(path)
  File.open(path,"r").each_line do |line|
    return true if line.index("spide_url|#{url}")
  end
  return false
end

代码思路:
1,安装httpclient 和 hpricot gem包
httpclient 是ruby 的http 库 , 可以模拟浏览器的操作,例如post数据等等 , 其他你还可以用ruby自带的NET::HTTP 库 , 还有mechanize额外库等 ,hpricot 是用来解析 html 的

2,扒取指定的页 , 例如 http://www.wxianfeng.cn/page/2/ 把这一页 所有 文章的url给抓出来 , 然后再对这一页的所有文章url再 抓取 , 分析 , 例如 http://www.wxianfeng.cn/page/2/ 这一页有 http://www.wxianfeng.cn/2009/12/18/firefox-live-bookmark-rss-ticker-%E4%BA%86%E8%A7%A3%E6%9C%80%E6%96%B0%E5%AE%9E%E6%97%B6%E4%BF%A1%E6%81%AF/ 的一篇文章的url

3,然后循环抓取不同的页

4,上面用到的 “md5″ 库, 是为了给抓取的图片生成名字

5, 所有抓取的内容 , 保存在文件中

6, 注意记录log , 以便分析抓取到哪了, 第二次执行的时候 , 抓取过的url 就next

7………..

全部源码地址 :
http://github.com/wxianfeng/wxianfeng_cn_spider

4 Comments

  1. guest
    Posted 2010年03月6日 at 2:12 下午 | Permalink

    你的Wp模板的css估计有问题 我用ff和chorme访问都有问题
    文章写的不错 希望以后能象你请教ror问题

  2. wxianfeng
    Posted 2010年03月8日 at 9:22 上午 | Permalink

    没有问题吧, 我用的就是 plain text theme , 只有白纸黑字的那种!

  3. bi
    Posted 2010年06月21日 at 5:05 下午 | Permalink

    如果把它改成抓取网页上的地址,又要怎样改动这些代码,烦告知下

  4. bi
    Posted 2010年06月21日 at 5:05 下午 | Permalink

    是邮箱地址

Post a Comment

Your email is never shared. Required fields are marked *

*
*