【问题标题】:mechanize with google autocomplete使用谷歌自动完成进行机械化
【发布时间】:2018-01-15 21:29:53
【问题描述】:

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

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。所以我潜入机械化。如果有 AirBnB API 链接,我们将不胜感激。

【问题讨论】:

  • 自动完成是一个 javascript 的东西,所以你需要 selenium。

标签: ruby-on-rails mechanize


【解决方案1】:

您的问题并没有真正包含问题,因此我对您要完成的工作的最佳尝试如下:

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

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

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

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

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

当您检查流量时,您会看到以下可在您的请求中发送的参数:

  • 页面
  • 持续时间
  • person_capacity
  • 房间类型
  • 加载中
  • sw_lat
  • sw_lng
  • 内拉特
  • 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”正在报告我的个人区域,无论纬度/经度如何变化,但货币价值实际上正在发生变化,并且与网站显示的内容相匹配。可能该属性基于 IP 位置,或者有问题。

虽然这些值似乎会随着 sw/ne 边界的更大和更小区域而缩放,但您也可以对两者使用相同的 lat/lng 并仍然获得结果。它可能无法准确反映 Google 地理编码器如何引用某个地点,但它可能足以满足您的使用需求。

一旦您有了获取 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)"}

【讨论】:

    猜你喜欢
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    • 2016-01-31
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    • 2019-08-06
    • 1970-01-01
    相关资源
    最近更新 更多