19824


[http://ja.aliexpress.com/wholesale?catId=0&initiative_id=AS_20151205231131&SearchText=bag+mens](http://ja.aliexpress.com/wholesale?catId=0&initiative_id=AS_20151205231131&SearchText=bag+mens)

を起点に、商品ページのURLリストを取得し、その数を出力します。  
たまに、期待した出力である6が出力されるのですが、  
下記のようなエラーが出てしまう時があります。エラー8割、正常2割くらいの割合です。  
何が原因かがわからず、途方に暮れています。  
何かヒントをいただけませんか？

[code]

    require 'open-uri'
    require 'nokogiri'
    require 'pstore'
    require 'anemone'
    require 'open_uri_redirections'
    require 'openssl'
    require 'selenium-webdriver'
    require 'capybara'
    require 'capybara/poltergeist'
    #require 'phantomjs'
    
    
    class Crawl
      def get_html_obj(url)
        Capybara.run_server = false
        Capybara.register_driver :poltergeist do |app|
          Capybara::Poltergeist::Driver.new(app, {js_errors: false})
        end
        session = Capybara::Session.new(:poltergeist)
        session.visit(url)
        return Nokogiri::HTML.parse(session.html)
      end
    
      def get_page_list(url)
        url_list = Array.new
        doc = get_html_obj(url)
        doc.css('div[class = "ui-pagination-navi util-left"]>a').each do |page|
          url_list << page.attribute("href").text 
        end
        url_list = url_list.sort_by do |k|
          /(.+)(page=)([\d]+)/ =~ k
          $3.to_i
        end
        return url_list.uniq
      end
    
      def get_page_list_all(url,n)
        url_list_all = Array.new
        crawl_url = Crawl.new
        last_url = url
    
        n.times do |n|
          url_list = crawl_url.get_page_list(last_url)
          last_url = url_list.last
    
          url_list_all.concat(url_list)
        end    
         url_list_all = url_list_all.sort_by do |k|
          /(.+)(page=)([\d]+)/ =~ k
          $3.to_i
        end
        return url_list_all.uniq
      end
    
      def get_product_list(url)
        url_list = Array.new
        doc = get_html_obj(url)
        doc.css('a[class = "history-item product "]').each do |page|
          url_list << page.attribute("href").text 
        end
    
        return url_list
      end
    
      def get_product_list_all(url,n)
        url_list = Array.new
        get_page_list_all(url,n).each do |url_tmp|
          doc = get_html_obj(url_tmp)
          doc.css('a[class = "history-item product "]').each do |page|
            url_list << page.attribute("href").text 
          end
        end
        return url_list
      end
    
    
      def get_product_obj(url)
        obj = Crawl.new
        return obj.get_html_obj(url)
      end
    
    
      def get_product_objs(url)
        obj = Crawl.new
        products = Array.new
        urls = obj.get_product_list(url)
    
        urls.each do |url|
          products << obj.get_html_obj(url)
        end
        return products
      end
    
      def get_product_objs_all(url,n)
        obj = Crawl.new
        products = Array.new
        urls = obj.get_page_list_all(url,n)
    
        urls.each do |url|
          products << obj.get_html_obj(url)
        end
        return products
      end
    end
    
    init_url = "http://ja.aliexpress.com/wholesale?catId=0&initiative_id=AS_20151205231131&SearchText=bag+mens"
    
    crawl = Crawl.new
    puts crawl.get_page_list(init_url).count
    
[/code]

[code]

    C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/poltergeist-1.8.1/lib/capybara/poltergeist/web_socket_server.rb:98:in `rescue in send': Timed out waiting for response to {"id":"8482ca9f-6a3d-40d2-b6b7-eb33c8327b41","name":"visit","args":["http://ja.aliexpress.com/wholesale?catId=0&initiative_id=AS_20151205231131&SearchText=bag+mens"]}. It's possible that this happened because something took a very long time (for example a page load was slow). If so, setting the Poltergeist :timeout option to a higher value will help (see the docs for details). If increasing the timeout does not help, this is probably a bug in Poltergeist - please report it to the issue tracker. (Capybara::Poltergeist::TimeoutError)
      from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/poltergeist-1.8.1/lib/capybara/poltergeist/web_socket_server.rb:94:in `send'
      from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/poltergeist-1.8.1/lib/capybara/poltergeist/server.rb:33:in `send'
      from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/poltergeist-1.8.1/lib/capybara/poltergeist/browser.rb:340:in `command'
      from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/poltergeist-1.8.1/lib/capybara/poltergeist/browser.rb:34:in `visit'
      from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/poltergeist-1.8.1/lib/capybara/poltergeist/driver.rb:95:in `visit'
      from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/capybara-2.5.0/lib/capybara/session.rb:232:in `visit'
      from C:/Users/Akinori/Documents/NetBeansProjects/RubyApplication1/lib/main2.rb:20:in `get_html_obj'
      from C:/Users/Akinori/Documents/NetBeansProjects/RubyApplication1/lib/main2.rb:26:in `get_page_list'
      from C:/Users/Akinori/Documents/NetBeansProjects/RubyApplication1/lib/main2.rb:109:in `<main>'
    
[/code]


CC BY-SA 3.0
2015-12-09T15:53:54.127
19822
2015-12-12T21:27:23.210
2015-12-09T22:30:12.027
85
13551
question
ruby web-scraping
Capybara, poltergeistでTimed out waiting for response toエラーが出る。


PoltergesitのTimeout問題はこちらのissueでも取り上げられています。

<https://github.com/teampoltergeist/poltergeist/issues/375>

上のissueを参考にして、過去にこんなオプションを設定したことがあります。  
これで試してみるといかがでしょうか？

[code]

    options = { js_errors: false, timeout: 180, phantomjs_logger: StringIO.new, logger: nil, phantomjs_options: ['--load-images=no', '--ignore-ssl-errors=yes'] }
    Capybara.register_driver :poltergeist do |app|
      Capybara::Poltergeist::Driver.new(app, options)
    end
    
[/code]

まだ同じエラーが出るようであればtimeout秒数を増やしてみてください。（180でも結構長いと思いますが）

## 追記

実際に動かしてみましたが、特にエラーは出ません。  
完了までに10秒弱かかりますが、タイムアウトは発生しませんでした。

ただし、何度か実行しているとそれまで表示されていた「6」が「0」になり、それ以降ずっと「0」が表示されています。  
HTMLをputsしたところ、ブラウザの表示とは異なる中国語のHTMLが出力されました。

次に、WebドライバをPhantomJSからSelenium（Firefox）に変更して、30回ほど連続実行したところ、途中から商品ページではなく、ログイン画面が表示されました。(サーバー負荷を考慮し、実行時は1回アクセスするたびに1秒のスリープを挟んでいます)

[code]

    # ...
      def get_html_obj(url)
        Capybara.run_server = false
        session = Capybara::Session.new(:selenium)
        session.visit(url)
        puts session.html
        return Nokogiri::HTML.parse(session.html)
      end
    # ...
    crawl = Crawl.new
    30.times do
      puts crawl.get_page_list(init_url).count
      sleep 1
    end
    
[/code]

推測するに、クローラやスクレイピングを禁止する仕組みがサイトに用意されている気がします。

タイムアウトした理由はよくわかりませんが、このサイトをスクレイピングするのは推奨されていないようなので、諦めた方が良いかもしれません。（スクレイピングを歓迎するサイトの方が珍しいとは思いますが・・・）

## 追記2

> これを防ぐには、proxyでアクセス毎にipアドレスを変えるのと、user agentを変える必要がありますか？
> また、ログイン画面が表示されたことを検出し、ログイン処理をcapybaraで行えばいいのでしょうか？

そのあたりまで踏み込んでしまうと、サイトの利用方法的にグレーゾーンに入ってしまいそうなので、回答しかねます。（そもそも僕もよくわかりません）

また、親サイト（？）の[Alibaba.comの利用規約3.2](http://rule.alibaba.com/rule/detail/2041.htm)には「許可なしにロボットによる情報収集を行ってはいけない」というような記述が見られます。

> Systematic retrieval of Site Content from the Sites to create or compile,
> directly or indirectly, a collection, compilation, database or directory
> (whether through robots, spiders, automatic devices or manual processes)
> without written permission from Alibaba.com is prohibited.

なので、最悪の場合、何か問題を起こして訴えられる、ということも起きかねません。（日本国内ですら[こういう事件](https://ja.wikipedia.org/wiki/%E5%B2%A1%E5%B4%8E%E5%B8%82%E7%AB%8B%E4%B8%AD%E5%A4%AE%E5%9B%B3%E6%9B%B8%E9%A4%A8%E4%BA%8B%E4%BB%B6)が起きてますので）

AliexpressにはどうやらAPIがあるようなので、そちらを利用した方が良いのではないでしょうか。

<http://portals.aliexpress.com/help/help_center_API.html>


CC BY-SA 3.0
2015-12-09T22:35:13.607
19824
2015-12-12T21:27:23.210
2015-12-12T21:27:23.210
85
85
19822
answer


何度もアクセスしていると、サーバー側がクローラーだと判断してレスポンスを返さなくなるのかもしれません。

<http://ja.aliexpress.com/robots.txt> には以下のように書かれており、少なくともBaiduのクローラーに対しては
[http://ja.aliexpress.com/wholesale?catId=0&initiative_id=AS_20151205231131&SearchText=bag+mens](http://ja.aliexpress.com/wholesale?catId=0&initiative_id=AS_20151205231131&SearchText=bag+mens)
へのアクセスを禁じているように見えます。

[code]

    # file: robots.txt,v 1.0 2002/09/23 created by Tsing Kong
    # www.alibaba.com
    # <URL:http://www.robotstxt.org/wc/exclusion.html#robotstxt>
    # Format is:
    #       User-agent: <name of spider>
    #       Disallow: <nothing> | <path>
    # -----------------------------------------------------------------------------
    User-agent: *
    Disallow: /search/
    Disallow: /productdetail/
    
    User-agent: Baiduspider
    Disallow: /promotion/
    Disallow: /wholesale?
    
    User-agent: baiduspider
    Disallow: /promotion/
    
[/code]


CC BY-SA 3.0
2015-12-10T10:08:37.830
19852
2015-12-10T10:08:37.830
2599
19822
answer