ruby-on-rails - 用谷歌自动完成 Mechanize

标签 ruby-on-rails mechanize

Mechanize 在此页面上找不到表格。所以我试图通过输入来填写。问题是该表单是 Google 自动完成的。首先我需要填写输入,然后从下拉列表中选择一个城市。所以我尝试过的是:

agent = Mechanize.new
page = agent.get("https://www.airbnb.com/host/homes")
location = agent.page.search(".earning-estimation__location-input")
location.at("input")['value'] = 'kiev'
location.at("input")[0].select

并得到:
NoMethodError: private method `select' called for nil:NilClass

附言首先我没有找到 AirBnB API。所以我潜入 Mechanize 。如果有 AirBnB API 链接,我们将不胜感激。

最佳答案

你的问题并没有真正包含一个问题,所以我对你想要完成的最好的尝试如下:

鉴于我在此页面上没有看到太多操作,我假设您希望获得各个区域的每周平均费率。

您实际上不需要根据自动完成填写下拉列表。这种交互是通过从 Google 地理编码 API 获取纬度/经度并将其传递给 https://www.airbnb.com/wmpw_data 来驱动的。 .

对于需要 javascript 才能运行的站点(像这样),您有两个选择:

  • 对他们使用的 API 进行逆向工程(例如下面的示例)
  • 使用像 Selenium/WebDriver 这样的框架,通过完全原生的浏览器来导航站点。

  • 要对 API 进行逆向工程,Web 调试代理工具是无价的。您可以通过查看浏览器开发工具的“网络”选项卡获得大量信息,但诸如“Fiddler”、“Charles Proxy”、“Burp”等内容是无价的。

    当您检查流量时,您会看到以下可用于在您的请求中发送的参数:
  • 持续时间
  • 人员容量
  • 房间类型
  • 加载中
  • sw_lat
  • sw_lng
  • ne-Lat
  • ne_lng

  • 您可以通过使用诸如
    [37] pry(main)> page.css("[data-room-type]").map{|n| n["data-room-type"]}.uniq
    => ["entire_home_apt", "private_room", "shared_room"]
    

    如果您将各种 lat/lng 值设置为适合您的值,您将获得该区域的每周平均价格。我注意到“localized_place”无论纬度/经度如何变化都在报告我的个人区域,但实际上货币值(value)正在发生变化,并且与网站显示的内容相匹配。也许该属性是基于 IP 位置的,或者有什么地方不对劲。

    虽然这些值似乎随着 sw/ne 边界的更大和更小区域而缩放,但您也可以对两者使用相同的 lat/lng 并仍然得到结果。它可能无法准确反射(reflect) Google Geocoder 引用地点的方式——但它可能足以满足您的使用需求。

    一旦您有了获取 lat/lng 的来源,您就可以将它们直接提供给他们的 API。

    这似乎是一个工作示例:
    require 'mechanize'
    agent = Mechanize.new
    page = agent.get "https://www.airbnb.com/host/homes"
    
    room_types = page.css("[data-room-type]").map{|n| n["data-room-type"]}.uniq
    
    # Values for near Charleston, WV, a random place from Google Maps
    sw_lat = '38.360928'
    sw_lng = '-81.6464767'
    ne_lat = sw_lat
    ne_lng = sw_lng
    duration = '1_week'
    person_capacity = 1
    room_type = room_types.first # => 'entire_home_apt'
    
    url = "https://www.airbnb.com/wmpw_data?page=slash_host&duration=#{duration}&person_capacity=#{person_capacity}&room_type=#{room_type}&loading=false&sw_lat=#{sw_lat}&sw_lng=#{sw_lng}&ne_lat=#{ne_lat}&ne_lng=#{ne_lng}"
    
    money = agent.get(url).body
    
    require 'json'
    JSON.parse(money)["data"]
    # => {"average_income_raw"=>385.0,
    #     "average_income"=>"$385",
    #     "localized_place"=>"xxx",
    #     "list_your_space_link"=>"https://www.airbnb.com/rooms/new",
    #     "earning_estimation_duration"=>"1_week",
    #     "localized_market"=>"Other (International)"}
    

    关于ruby-on-rails - 用谷歌自动完成 Mechanize ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45566154/

    相关文章:

    ruby-on-rails - 在 Heroku 上部署 Ruby on Rails 应用程序时出现 "postgresql gem is not loaded"错误

    ruby-on-rails - 未定义的方法 `full_title'

    ruby Mechanize : Programmatically Clicking a Link Without Knowing the Name of the Link

    ruby - 获取 OpenSSL::SSL::SSLError:证书验证失败 - 具有最新 ca 包的事件

    ruby-on-rails - 如何在 Ruby on Rails 中分析请求?

    ruby-on-rails - 值未存储在 ruby​​ on rails 数组中

    Ruby mechanize 未获取完整内容

    perl - Perl Mechanize 和代理的问题

    ruby-on-rails - 无法在 Ubuntu 15.04 上安装 Ruby 2.2.3

    php - Cucumber、webrat Mechanize 在 MAMP 上测试 php/drupal 应用程序、身份验证问题