`

构建自己的DSL之一 Simple Crawler

阅读更多
转载请标明出处:http://fuliang.iteye.com/blog/1122008

经常需要从网上抓取一些需要的内容做成语料,供分类使用。所以需要一个灵活的抓取、抽取程序-自己的DSL来做这件事,这样每次只需要写几行代码就能得到需要的内容。比如我比较希望以下几行代码就能把我的博客的内容给抓下来:

crawler = Crawler.new
1.upto(10) do |pn|
    urls = []
    crawler.fetch "http://fuliang.iteye.com/?page=#{pn}" do |page|
        page.css("div.blog_title > h3 > a").each do |node|
            urls << "http://fuliang.iteye.com#{node.attributes['href']}"
        end
    end

    urls.each do |url|
        crawler.fetch url do |page|
            page.xpath(:title => '//*[@id="main"]/div/div[2]/h3/a',:content => '//*[@id="blog_content"]').each do |entry|
                printf("%s\t%s\n",entry[:title].text.gsub(/\s+/,""),entry[:content].text.gsub(/\s+/,""))
            end
        end
    end
    break
end


我们先创建一个Crawler对象,然后按照我博客的列表页分页特征,得到第pn页的url是
http://fuliang.iteye.com/?page=#{pn},当然有可能有复杂的规则,构建列表页的url列表,然后遍历。crawler只有一个fetch方法,就可以把页面fetch下来,然后得到这个页面在块中处理。这个页面可以直接根据xpath、css来得到需要抽取的内容,还可以一次抽取一个记录,只需要向xpath,css方法中传递一个字段到xpath/css的hash,然后得到对应的记录的hash。
按照上面的描述,我们先编写一个简单的Crawler,为了防止被封我们使用了几个代理:
class Crawler
    def initialize
        @proxies = 1.upto(6).collect{|index| "http://l-crwl#{index}:1080"}
    end

    def fetch(url)
        yield Page.new( Nokogiri::HTML(open(url,fetch_options)) )
    end

private
    def rand_proxy
        @proxies[(rand * 6).to_i]
    end

    def fetch_options
        user_agent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2) Gecko/20061201 Firefox/2.0.0.2 (Ubuntu-feisty)"

        fetch_options = {
            "User-Agent" => user_agent,
            "proxy" => rand_proxy
        }
    end
end

然后我们定义Page类,动态定义了css和xpath的方法,我们直接代理给Nokogiri
的css、xpath,让它来做事情,我们收集一下抽取的结果,一些就ok了:
class Page
    def initialize(html)
        @html = html
    end

    class_eval do
        [:css,:xpath].each do |extract_by|
            define_method extract_by do |arg,&block|
                if arg.is_a? String then
                    if block.nil? then
                       @html.send(extract_by,arg)
                    else
                        block.call(@html.send(extract_by,arg))
                    end
                elsif arg.is_a? Hash then
                    extract_raw = arg.collect{|key,value| [key, @html.send(extract_by,value)]}
                    data = extract_raw.collect do |key, vals|
                        ([key] * vals.size).zip(vals)
                    end
                    result =  data[0].zip(*data[1..-1]).collect{|e| Hash[ * e.flatten ]}
                    if block.nil? then
                        result
                    else
                        block.call(result)
                    end
                else
                    raise ArgumentError.new('Argument type must String or Hash type')
                end
            end
        end
    end
end


整个的代码:
#!/usr/bin/env ruby

require 'rubygems'
require 'nokogiri'
require 'open-uri'

class Crawler
    def initialize
        @proxies = 1.upto(6).collect{|index| "http://l-crwl#{index}:1080"}
    end
    
    def fetch(url)
        yield Page.new( Nokogiri::HTML(open(url,fetch_options)) )
    end

private
    def rand_proxy
        @proxies[(rand * 6).to_i]  
    end

    def fetch_options  
        user_agent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2) Gecko/20061201 Firefox/2.0.0.2 (Ubuntu-feisty)"

        fetch_options = {  
            "User-Agent" => user_agent,  
            "proxy" => rand_proxy  
        }  
    end  
end

class Page
    def initialize(html)
        @html = html
    end

    class_eval do
        [:css,:xpath].each do |extract_by|
            define_method extract_by do |arg,&block|
                if arg.is_a? String then
                    if block.nil? then 
                       @html.send(extract_by,arg)
                    else
                        block.call(@html.send(extract_by,arg))
                    end
                elsif arg.is_a? Hash then
                    extract_raw = arg.collect{|key,value| [key, @html.send(extract_by,value)]}
                    data = extract_raw.collect do |key, vals|
                        ([key] * vals.size).zip(vals)
                    end
                    result =  data[0].zip(*data[1..-1]).collect{|e| Hash[ * e.flatten ]}
                    if block.nil? then
                        result
                    else
                        block.call(result)
                    end
                else
                    raise ArgumentError.new('Argument type must String or Hash type')
                end
            end
        end
    end
end

crawler = Crawler.new
1.upto(10) do |pn|
    urls = []
    crawler.fetch "http://fuliang.iteye.com/?page=#{pn}" do |page|
        page.css("div.blog_title > h3 > a").each do |node|
            urls << "http://fuliang.iteye.com#{node.attributes['href']}"
        end
    end

    urls.each do |url|
        crawler.fetch url do |page|
            page.xpath(:title => '//*[@id="main"]/div/div[2]/h3/a',:content => '//*[@id="blog_content"]').each do |entry|
                printf("%s\t%s\n",entry[:title].text.gsub(/\s+/,""),entry[:content].text.gsub(/\s+/,""))
            end
        end
    end
    break
end
3
2
分享到:
评论

相关推荐

    simple web crawler using .net

    这个项目“simple web crawler using .NET”是基于微软的.NET框架实现的一个基本的网络爬虫。它能够遍历网页,抓取指定网站的数据,帮助开发者或者研究人员快速获取大量网页信息。 【描述】"源代码:使用.NET实现的...

    multi-thread-simple-crawler-socket.rar_Simple Socket_crawler_soc

    标题中的"multi-thread-simple-crawler-socket.rar_Simple Socket_crawler_soc"暗示了这是一个关于多线程简单爬虫的项目,使用了Socket通信技术。在描述中提到的是一个基于C#的Socket通信实现的聊天室源代码,适用于...

    Simple-Web-Crawler-master_爬虫_

    【标题】"Simple-Web-Crawler-master_爬虫_" 是一个C#编写的简单网络爬虫项目的源码库。这个项目旨在提供一个基础的、易于理解的实例,帮助初学者和开发者了解如何在C#环境下实现网页数据抓取的功能。 【描述】"C# ...

    Python爬虫示例之distribute-crawler-master.zip

    Python爬虫示例之distribute_crawler-master.Python爬虫示例之distribute_crawler-master.Python爬虫示例之distribute_crawler-master.Python爬虫示例之distribute_crawler-master.Python爬虫示例之distribute_...

    爬虫crawler4j源码+实例

    `crawler4j` 是一个开源的Java库,专为网络爬虫开发而设计。这个库由Elianne Damiaan创建,提供了一种简单且高效的框架,用于构建多线程的Web爬虫。在本文中,我们将深入探讨`crawler4j`的核心概念、功能以及如何...

    crawler4j-4.0

    `crawler4j-4.0` 是一个基于Java的网页爬虫...总之,`crawler4j-4.0`提供了一个强大而易用的框架,用于构建Java网络爬虫。通过深入学习和实践,开发者可以快速构建自己的爬虫应用,有效地抓取和处理互联网上的数据。

    crawler-master_crawler_

    【标题】"crawler-master_crawler_" 指的可能是一个关于网络爬虫的项目,其中 "master" 通常表示这是项目的主要分支或者是最完整的版本。"crawler" 是这个项目的关键词,意味着它涉及到互联网数据抓取的技术,即网络...

    WebCrawler

    WebCrawler利用Java的强大功能,构建了一个稳定的爬虫系统,可以高效地处理HTTP请求和响应,同时保证了代码的可维护性和扩展性。 2. **精细爬虫**: 这意味着WebCrawler可以精准地定位并抓取用户感兴趣的特定网页...

    simple-web-crawler

    该项目包含一个具有主要方法的JettyServer.java文件,该文件使用运行在localhost:8080 / simple-web-crawler上的Web搜寻器应用程序启动Jetty服务器。 该存储库包含整个eclipse项目,并且需要Gradle进行依赖项管理...

    crawler spider web爬虫

    【标题】"Crawler Spider Web爬虫"是一个基于C++实现的网络爬虫项目,它旨在高效地抓取和处理互联网上的网页数据。...对于想要学习或构建自己爬虫系统的开发者而言,这个项目提供了有价值的参考和实践素材。

    Focused Crawler 聚焦爬虫

    ### Focused Crawler (聚焦爬虫):一种基于本体的聚焦爬虫方法 #### 摘要 本文介绍了一种新型的聚焦爬虫构建方法。聚焦爬虫的主要目标是有效地识别与预定义主题相关的网页,并下载这些页面,而不考虑它们在网络中...

    crawler4j源码

    【标题】"crawler4j源码" 是一个用于网络爬虫开发的开源库,它为Java开发者提供了一种简单易用的方式来实现网页抓取。这个库由Ahmet Alp Balkan和Ali Sol编写,旨在简化网页抓取过程,使得开发者可以专注于业务逻辑...

    Windows-Web-Crawler-Proxy.rar_Simple-Web-Crawler_crawler_proxy_w

    爬虫程序,想学习的朋友们,可以下载。对于学习非常有帮助。

    Crawler

    综上所述,这个"Crawler"项目提供了一个学习和实践网络爬虫技术的机会,尤其是对于使用C++开发爬虫的同学,可以从源码中学习到如何在C++环境下实现网络请求、HTML解析、数据提取等功能,并了解如何构建一个完整的...

    ex-crawler

    Ex-Crawler 是一款基于 Java 开发的网页抓取工具,专为高效且灵活的数据采集而设计。这款爬虫软件分为两个主要组件:一个是守护进程(Daemon),另一个是可配置的 Web 爬虫。这样的架构使得 Ex-Crawler 具有高度的...

    Simple-Web-Crawler-master.zip_网络数据收集

    "Simple-Web-Crawler-master"是一个典型的网络爬虫项目,旨在帮助用户自动收集特定网站的数据。 在"Simple-Web-Crawler-master.zip"这个压缩包中,我们很可能会找到一个完整的爬虫框架,包括了源代码、配置文件以及...

    appcrawler自动化测试实践.pdf

    appcrawler是一款用于移动应用自动化测试的工具,尤其适用于进行稳定性测试。它基于Scala编程语言,并运行在Java虚拟机(JVM)上,利用“UI遍历”的理念,对应用程序的界面元素进行全面操作。通过配置规则,app...

    crawler4j-4.1-jar-with-dependencies

    _crawler4j_ 是一个用Java编写的开源Web爬虫框架,它提供了一个简单易用的API,用于构建多线程Web爬虫。这个框架适用于学术研究、数据挖掘和自动化测试等多个场景。主要特性包括: 1. **多线程**:支持多线程爬取,...

    Crawler4j-3.5 源码 类包 依赖包

    **Crawler4j** 是一个基于Java实现的轻量级网页爬虫框架,它提供了简单易用的API,使得开发者可以快速构建自己的网络爬虫应用。Crawler4j-3.5 版本包含了该框架在2014年4月6日从Google Code迁移时的最新源代码、编译...

Global site tag (gtag.js) - Google Analytics