lcomplete 的技术分享
关于
博客
推特
邮箱订阅
RSS 订阅
GitHub
关于
博客
推特
邮箱订阅
RSS 订阅
GitHub
  • 野生架构师周刊

    • 019 ✨ 从凯文·凯利的建议中找到对自己有用的那 10%
    • 018 🙊 Less Is More
    • 017 🏅 成为职场优秀程序员的 5 个建议
    • 016 🐒 野生架构师成长之路(1)——游戏与现实、乌龟与火箭
    • 015 🍻 内卷时代的软件和自媒体
    • 014 🚮 中国互联网的三个问题
    • 013 🔭 重新掌控自己的信息
    • 012 📸 Old But Good 、UNIX 艺术、互联网历史博物馆
    • 011 🖼 Browser = OS 、文章、工具、资源、文摘、言论
    • 010 🚀 Hacking The Mind / 拆掉思维里的墙、放飞想象、打破规则
    • 009 🌈 Newsletter Of Newsletters、海绵宝宝的智慧
    • 008 📚 Notion vs Obsidian、程序设计 vs 软件工程
    • 007 🍀 十年后重新使用 RSS 给我带来的巨变
    • 006 📒 与人保持联系的系统、用低代码应用设计产品原型、万能锤
    • 005 ⚙️ IFTTT 和 Zapier 使用对比、最好的效率系统、投入产出比最高的 3 件事
    • 004 🧛‍♂ 备受程序员喜爱的暗黑主题、程序员的英语有多重要、Newsletter 资源分享
    • 003 🐂 新一代 kubernetes、反脆弱
    • 002 🕷 Web 3.0、关于好品味的商业模式
    • 001 🐣 低代码、我的信息管理
  • Java

    • 俯瞰 Java 服务端开发
    • Java 工程师能力提升路径(一):从业余到专业
    • Java 学习大法
    • [Java] 5 分钟搞定 liquibase 数据库版本控制
    • [Java] 高级工程师的自我修养之单元测试(一):DAO 层测试
    • [Java] 你还在统一返回 ApiResultBean 吗?✋ duck 不必,快来看 API 错误处理的最佳实践 ✔️
    • [Java] Spring 项目开发最佳实践
  • 数据库

    • MySQL 数据库开发规范
  • 软件工程

    • 万字长文带你彻底搞懂什么是 DevOps
    • 网站项目 Git 使用流程和规范
  • Javascript

    • 🎄 [React] 使用 remotion 制作视频,让圣诞快乐 PSD 动起来
    • [Javascript] 使用 lit 编写 Web Components 简化 Layui 代码
  • 编程人生

    • 编码的道与禅
    • 程序员的职业素养
    • 研发质量与效率的绩效指标设计
    • 编程界的 51 条名言佳句
  • 编程语言

    • 七周七语言之使用 prolog 解决爱因斯坦斑马难题
    • 七周七语言之用 ruby 做点什么
  • 效率

    • [10 倍程序员] ⭐ 脚本的魅力,内含 js 写爬虫、python 骚操作等实用代码
    • [10 倍程序员] ⭐ 51W+ 的终端命令行工具助你成为 10 倍程序员
    • 我的效率工具箱
    • 使用开源工作流自动化工具 n8n 打造个人助理
    • 我如何流畅地切换使用 Mac 和 Windows(一)

一段简单的ruby爬虫代码

每学一门语言,思维方式都会发生改变,编程语言亦是如此。

编程语言从范型上来划分,主要有过程式语言、面向对象式语言和函数式语言,只有了解这些语言的变化、发展和设计哲学,深入地学习它们,才能够将它们融汇贯通,体会到不同范型中的精华和思想。如今有众多的编程语言,五花八门,《七周七语言》中挑选了7门优秀的语言进行讲解,这些语言包括了以上三种范型,其中有Ruby这样的面向对象的脚本语言、Io这样的原型语言、Haskell这样的纯函数式语言,也有Scala这种融合了函数式编程和面向对象编程的语言,这些语言都有其特别的设计和独门绝技,比如Ruby的简洁、效率和它的元编程特性。

本次用Ruby写了一段抓取程序,可以抓取煎蛋上评分较高的有趣图片,其中解析html用到了nokogiri模块。这段程序总共只有几十行代码,为了多使用一些语言上的特性,还加了一些没必要的代码,如果再精简一下的话,这段程序可以非常简短,实在是不得不佩服ruby的简洁和效率。

不多说了,直接上代码吧!

#encoding: utf-8

require 'net/http'
require 'open-uri'
require 'nokogiri' # 用于解析html的模块
                   # sudo apt-get install libxslt-dev libxml2-dev 
                   # sudo gem install nokogiri
require 'pathname'

class JanDanSpider
    attr_accessor :base_uri, :cur_page # 定义属性访问器

    def initialize(pagesize)
        @base_uri = 'http://jandan.net/pic' # @表示实例变量、@@表示类变量、$表示全局变量
        @dir = '/media/Develop/MyCode/SevenLang/ruby/pic'
        @pagesize = Integer(pagesize) # 整型转换
    end

    def crawl()
        Dir.mkdir @dir unless File.directory? @dir # 表判断的方法结尾都有个?
        totalpage = crawlpage(0)
        puts "pagesize #{totalpage}" # ""字符会引发字符串替换,''则不会
        (1..@pagesize-1).each do |i| # 遍历元组
            crawlpage(totalpage - i)
        end
        puts 'complete!'
    end

    def crawlpage(page)
        url = page==0 ? @base_uri : @base_uri+'/page-'+page.to_s # to_s是必要的
        puts "crawl-page: #{url}"

        fpage = open(url)
        html = fpage.read
        doc = Nokogiri::HTML(html)
        doc.css('ol.commentlist li').each { |comment|
            match = /comment-(\d+)/.match(comment['id'])
            if match
                id = match[1]
                oo = Integer(comment.css('#cos_support'+'-'+id)[0].content);
                xx = Integer(comment.css('#cos_unsupport'+'-'+id)[0].content);
                xx = 1 if xx==0
                if(oo>xx && (oo>200 || oo/xx >10) )
                    src = comment.css('p img')[0]["src"]
                    puts "crawl: oo #{oo} xx #{xx} src #{src}"
                    save_pic(src)
                end
            end
        }
        if page==0
            cur_page = doc.css(".current-comment-page")[0].content
            page = Integer(/\d+/.match(cur_page).to_s)
        end
        puts "page #{page} done!"
        page # ruby中每条语句都有返回值,函数内最后一条语句的返回值会被return
    end

    def save_pic(url)
        urlpath = Pathname.new(url)
        filename = urlpath.basename.to_s
        dirpath = Pathname.new(@dir)
        filepath = dirpath.join(filename).to_s
        open(url) { |fin|
            open(filepath,"wb") { |fout|
                while buf = fin.read(4096) do
                    fout.write buf
                end
            }
        } unless File.exists? filepath # 仅当文件不存在时进行抓取
        puts 'done!'
    end

end

if ARGV.length == 1
    spider = JanDanSpider.new($*[0]) # 可从 ARGV 或 $* 读取命令行参数
    spider.crawl()
else
    puts 'please input pagesize' #tip: puts, 转义+换行符 print, 转义 p, 换行
end
最后更新: 1/11/26, 7:08 PM
Contributors: lcomplete
Prev
七周七语言之使用 prolog 解决爱因斯坦斑马难题