今天用 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………..
4 Comments
你的Wp模板的css估计有问题 我用ff和chorme访问都有问题
文章写的不错 希望以后能象你请教ror问题
没有问题吧, 我用的就是 plain text theme , 只有白纸黑字的那种!
如果把它改成抓取网页上的地址,又要怎样改动这些代码,烦告知下
是邮箱地址