Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

HTTPと Webクローリングについて

485 views

Published on

Ruby, HTTP, crawler

Published in: Technology
  • Be the first to comment

  • Be the first to like this

HTTPと Webクローリングについて

  1. 1. HTTPリクエストと WEBクローリングについて 2019/01/16 大手町.rb #13
  2. 2. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 1自己紹介 Tomoya Kawanishi a.k.a. @cuzic エネチェンジ株式会社 チーフエンジニア 電力会社、ガス会社を切り替えるなら、エネチェンジ経由で! 一般家庭も!法人も! Ruby関西の中の人 発表者として登壇くださる方、あとで声かけください。 大手町.rb の中の人 毎月 大手町.rb の開催を予定 東京駅、各線大手町駅から直結! Ruby の初級者がメインターゲット
  3. 3. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 今日のテーマ HTTPリクエストと WEBクローリング について Ruby には HTTP クラスが標準 標準以外にもいろいろ便利な gem がある 自分で調べるのは大変 いろいろ紹介していきます 2
  4. 4. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 Ruby 標準ライブラリでの HTTPリクエスト Net::HTTP とても機能豊富なリッチな API POST、PUT、PATCH、DELETE コネクションの使いまわし プロキシの利用 ベーシック認証 HTTPリクエストヘッダの設定 多くの場合ここまでの機能は不要 リダイレクトの処理とか、面倒だからあまりオススメできない 3 uri = URI('http://example.com/some_path?query=string') body = Net::HTTP.get(uri)
  5. 5. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 Net::HTTP 4 uri = URI('http://example.com/some_path?query=string') # Net::HTTP.get body = Net::HTTP.get(uri) # Net::HTTP.get_response res = Net::HTTP.get_response(uri) puts res.body if res.is_a?(Net::HTTPSuccess) # Net::HTTP::Get res = Net::HTTP.start(uri.hostname, uri.port) do |http| req = Net::HTTP::Get.new(uri) http.request(req) end puts res.body if res.is_a?(Net::HTTPSuccess)
  6. 6. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 net/http のリダイレクト処理(ruby-doc での例) 5 def fetch(uri_str, limit = 10) # You should choose a better exception. raise ArgumentError, 'too many HTTP redirects' if limit == 0 response = Net::HTTP.get_response(URI(uri_str)) case response when Net::HTTPSuccess then response when Net::HTTPRedirection then location = response['location'] warn "redirected to #{location}" fetch(location, limit - 1) else response.value end end print fetch('http://www.ruby-lang.org')
  7. 7. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 6open-uri open を使って簡単に HTTPアクセスできる Ruby の既存メソッドの再定義機能を使った初期の好例 一般に知られるよりもはるかに高機能 ただ、GET以外(POST等)のリクエスト等はできない カンタンな例 open("http://www.ruby-lang.org/") {|f| f.each_line {|line| p line} } # open の返り値を使う例 body = open("http://www.ruby-lang.org/") {|f| f.read } body = open("http://www.ruby-lang.org/", &:read) # URI を使う例 uri = URI("http://www.ruby-lang.org/en/") body = uri.read
  8. 8. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 open-uri はいろいろできる 7 url = "http://www.example.com/" # プロキシの利用1 body = open(url, proxy: "http://proxy.example.com:8000/", &:read) # プロキシの利用2 ENV["http_proxy"] = "http://proxy.example.com:8000/" body = open(url, &:read) # プロキシの無効化 body = open(url, proxy: nil, &:read) # User-Agent の設定 body = open(url, "User-Agent" => "Ruby/#{RUBY_VERSION}", &:read) # ベーシック認証 auth = ["username", "password"] body = open(url, :http_basic_authentication => auth, &:read) # 3秒で open-timeout, 10秒で read-timeout body = open(url, open_timeout: 3, read_timeout: 10, &:read) # redirect を無効化(デフォルトは有効) body = open(url, redirect: false, &:read)
  9. 9. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 open-uri でプログレスバー 8 require 'open-uri' require 'ruby-progressbar' url = "http://www.example.com" content_length = nil progress_bar = nil body = open(url, content_length_proc: ->{ |content_length| break if content_length progress_bar = ProgressBar.create(total: content_length) }, progress_proc: ->{ |transferred_bytes| if progress_bar progress_bar.progress = transferred_bytes else puts "#{transferred_bytes} / Total size is unknown" end }, &:read )
  10. 10. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 HTTPリクエストができるいろんな gem httparty いちばん人気?機能豊富 rest-client これもとても人気 9 # HTTParty require 'httparty' url = "http://www.example.com/" response = HTTParty.get(url) # rest-client require 'rest-client' response = RestClient.get(url) # httpclient require 'httpclient' response = HTTPClient.get(url) # excon require 'excon' response= Excon.get(url) # typhoeus require "typhoeus" response = Typhoeus.get(url)
  11. 11. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 それぞれ、メリットデメリットがある お手軽さ。使い方がカンタンか open-uri が一番お手軽でベンリ 機能の豊富さ、人気さ HTTParty や rest-client あたりが人気で機能も豊富 特にクッキーまわりをやってくれるのは便利 スピード typhoeus 内部で libcurl を使っている em-synchrony/em-http 内部で IO を高速化できる API libev を使っている エラー表示の分かりやすさ Open3 で wget や curl を実行するとか デバッグ出力すると、詳細なエラーがかんたんに得られる 安定しない初期実装では便利。 stub 等が利用しにくい欠点がある。 10
  12. 12. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 WEBクローリングができる gem JS の処理が不要なとき Mechanize ログイン、cookie の処理などもやってくれる かなり広く使われていた Upton rest-client と nokogiri を内部的に利用 「次のページ」のような pagenation 処理が簡単にできる Wombat WEBページから JSON 形式の構造化データを簡単に生成できる DSL がキレイ JSの処理が必要なとき selenium-webdriver capybara-webkit 中間者プロキシを使ってブラウザ操作の通信を保存、 加工してスクレイピングする手法もある。 この方が高速に動作し、快適なことも多い 11
  13. 13. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 HTTP 、クローリングに必要な知識 1/2 URI(Uniform Resource Identifier) コンテンツ(リソース)がある場所を示す文字列 例: http://www.example.com/example/path?query=1 Ruby では標準ライブラリの uri で処理する HTTPクライアント サーバと HTTP リクエスト・レスポンスの通信を行う open-uri や rest-client などが代表的 クッキー ステートレスな HTTP でステートフルな情報を保持する機構 Ruby では各 HTTP クライアントごとに扱い方が異なる HTML/XML Parser HTML 文字列をパースし、XML Selector や CSS Selector で指 定したエレメントの情報を取得できるようにする Ruby で扱うライブラリとしては nokogiri が一般的 12
  14. 14. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 HTTP 、クローリングに必要な知識 2/2 HTTP プロキシ 内部ネットワークから外部にアクセスするとき仲介するサーバ 国内の IPアドレス限定サービスで、プロキシが必要なこともある ほぼすべての HTTP クライアントがプロキシの利用に対応している Man-in-the-Middle Proxy 中間者プロキシ 下記みたいな利用ができる Man-in-the-Middle プロキシを設定。ブラウザでそちらに向ける ブラウザでログイン。表示したいページ等を表示する Man-in-the-Middle プロキシで一連のブラウザ操作を保存。 保存した通信を加工。pagenation、画像・動画の保存等を自動実行 Ruby なら ritm。Python なら mitmproxy。 13
  15. 15. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 その他のオススメのメソッド・gem VCR HTTP 通信を保存して再実行できる テストでとても便利 レスポンスが遅いサービスを開発しているとき、 リクエスト・レスポンスを高速化し、作業効率を改善できる WebMock HTTPリクエストを stub できる 実際にはテスト先のサーバと通信しないようにできる VCR gem でも内部的に使われている Object#to_query ActiveSupport にある。特に Hash#to_query がベンリ 14 {name: 'David', nationality: 'Danish'}.to_query # => "name=David&nationality=Danish"
  16. 16. 大手町.rb #13 「HTTPリクエスト・WEBクローラについて」 まとめ HTTP リクエストを行うことはとても多いです。 マイクロサービスアーキテクチャで外部システムを利用する場合 WEBクローラを作成している場合 HTTPリクエストをしたい場合 単純に open-uri を使うのが案外オススメです。 案外高機能です。 遅いことが問題になって初めてほかの方法を検討しましょう 今回は全体的に発展的な話題が多い回でした。 詳細はあまり説明していないので、必要な人は 各自検索して調べてみてください。 15
  17. 17. ご清聴ありがとう ございました

×