Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to collect content form Web

How to collect content form Web

Jason Lee

July 27, 2012
Tweet

More Decks by Jason Lee

Other Decks in Programming

Transcript

  1. 如何编写数据采集器
    Jason Lee
    12年7月27⽇日星期五

    View Slide

  2. Nokogiri
    Python
    Ruby
    Regexp
    12年7月27⽇日星期五

    View Slide

  3. Hello world
    require "nokogiri"
    require "open-uri"
    doc = Nokogiri::HTML(open("http://www.cnbeta.com"),nil, "gbk")
    doc.css(".newslist .topic a").each do |a|
    puts "#{a.text} - #{a.attr("href")}"
    end
    摩托罗拉移动总部将搬⾄至芝加哥 涉及3000⼈人 - /articles/199038.htm
    步步惊⼼心!解密Google千兆宽带如何降低成本 - /articles/199037.htm
    不肯服输 苹果成功申请暂缓执⾏行道歉裁决 - /articles/199035.htm
    [最新]摩托罗拉Android机型在德国被禁售 - /articles/199034.htm
    Windows Phone 8版IE 10新特性侧漏 - /articles/199033.htm
    [视频]⽇日本研发新⼀一代商店付费⽅方案BacaryScan - /articles/199032.htm
    ⾕谷歌搜索结果⻚页⾯面再改版 左侧全留⽩白 - /articles/199031.htm
    [视频]预留摄像头位置 ⾕谷歌Nexus 7平板拆机视频曝光 - /articles/199029.htm
    [图]苹果2006年iPhone原型设计曝光 - /articles/199028.htm
    你所不了解的中国字库产业链 - /articles/199027.htm
    .....
    12年7月27⽇日星期五

    View Slide

  4. Problems
    • 编码
    • 需要登陆
    • ⻚页⾯面请求频率限制
    • 不规则的内容结构
    • Javascript 产⽣生的内容
    • 列表到⼦子⻚页内容
    • 图⽚片以及其他⼀一些资源⽂文件
    • 需要 POST 请求才能访问的⻚页⾯面,⽐比如搜房⺴⽹网 Asp.net 的翻
    ⻚页;
    12年7月27⽇日星期五

    View Slide

  5. 编码问题
    Nokogiri::HTML(open("http://www.cnbeta.com"),nil, "gbk")
    GB2312
    Nokogiri::HTML(open("http://www.cnbeta.com"))
    UTF-8
    12年7月27⽇日星期五

    View Slide

  6. 需要登陆的⻚页⾯面
    12年7月27⽇日星期五

    View Slide

  7. require 'mechanize'
    agent = Mechanize.new
    agent.get("http://www.douban.com/accounts/login")
    form = agent.page.forms.first
    # email
    form.fields[2].value = "[email protected]"
    # password
    form.fields[3].value = "jiubugaoshuni"
    form.submit
    agent.get("http://www.douban.com/accounts/")
    puts agent.title
    https://github.com/tenderlove/mechanize
    12年7月27⽇日星期五

    View Slide

  8. 访问频率限制
    • 设定 200ms 延迟每次⻚页⾯面请求;
    • ⽤用 Memcached 控制全局的⻚页⾯面下载频率;
    class GlobalFetcher
    def self.read(url)
    return false if !self.allow?
    self.hint
    open(url).read
    end
    def self.hint
    Rails.cache.increment("global_fetcher_#{Time.now.strftime("%Y%m%d%H%M")}"
    , 1)
    end
    def self.count
    Rails.cache.read("global_fetcher_#{Time.now.strftime("%Y%m%d%H%M")}"
    ).to_i || 0
    end
    def self.allow?
    self.count < 40
    end
    end
    每分钟 40 次请求
    12年7月27⽇日星期五

    View Slide

  9. 不规则的结构

    导演: 盖瑞·罗斯

    编剧: 苏珊·科林斯 / ⽐比利·雷 / 盖瑞·罗斯

    主演: 詹妮弗·劳伦斯 / 乔什·哈切森

    IMDb链接: tt1392170



    导演: 盖瑞·罗斯

    主演: 詹妮弗·劳伦斯 / 乔什·哈切森

    语⾔言: 英⽂文 / 法语

    国家: 美国

    IMDb链接: tt1392170


    Sometimes like this:
    12年7月27⽇日星期五

    View Slide

  10. AJAX 内容
    12年7月27⽇日星期五

    View Slide

  11. ⼦子⻚页⾯面
    doc = Nokogiri::HTML(open("http://www.cnbeta.com"),nil, "gbk")
    doc.css(".newslist .topic a").each do |a|
    fetch_content(a.attr("href"))
    end
    def fetch_content(path)
    doc = Nokogiri::HTML(open("http://www.cnbeta.com#{path}"),nil, "gbk")
    ...
    end
    12年7月27⽇日星期五

    View Slide

  12. 需要验证码?
    这是⼤大难题...
    12年7月27⽇日星期五

    View Slide

  13. 技巧
    • 通过 RSS 或其他 API 关注内容更新;
    • 下载⻚页⾯面的⽅方法加⼊入 caching 提升下次⽆无意访问到同样⻚页⾯面的
    速度,例如: open-uri-cached;
    • 伪造 http_referer,以破解某些⽐比较弱的图⽚片防盗链;
    • 设定登对⺴⽹网站级别的访问延迟控制(Memcached),以防⽌止
    速度过快被屏蔽 IP;
    • 通过 CSS Selector + Regexp 采集⼀一些⽆无规则的结构;
    • 仔细分析,猜测,找出⻚页⾯面/URL 规则,拿到⼀一些隐藏的内
    容;
    12年7月27⽇日星期五

    View Slide

  14. 其他学习资源
    • http://railscasts.com/episodes/173-screen-scraping-with-
    scrapi
    • http://railscasts.com/episodes/190-screen-scraping-with-
    nokogiri
    • http://railscasts.com/episodes/191-mechanize
    12年7月27⽇日星期五

    View Slide

  15. End
    http://huacnlee.com
    12年7月27⽇日星期五

    View Slide