2017-08-08 2 views
0

Mécaniser ne trouve pas les formulaires sur cette page. Donc, j'essaie de remplir en entrée. Le problème est que le formulaire est Google autocomplete. Et d'abord je dois remplir l'entrée, puis sélectionner une ville dans la liste déroulante. Donc ce que j'ai essayé est le suivant:mécaniser avec google autocomplete

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 

et obtenez:

NoMethodError: private method `select' called for nil:NilClass 

post-scriptum Premièrement, je n'ai pas trouvé d'API AirBnB. Alors je plonge dans la mécanisation. S'il y a un lien API AirBnB est apprécié.

+0

Autocomplete est une chose javascript afin que vous avoir besoin de sélénium pour cela. – pguardiario

Répondre

1

Votre question ne contient pas vraiment une question, donc mon meilleur coup de couteau à ce que vous cherchez à accomplir est la suivante:

Étant donné que je ne vois pas beaucoup d'une action sur cette page, je supposons que vous cherchez à acquérir les taux moyens hebdomadaires pour diverses zones.

Vous n'avez pas vraiment besoin de remplir le menu déroulant en fonction de l'auto-complétion. Cette interaction est alimentée en obtenant le lat/lon à partir des API de géocodage de Google, et en passant cela à https://www.airbnb.com/wmpw_data.

Pour les sites qui nécessitent de javascript pour fonctionner (comme celui-ci), vous avez deux options:

  • Désosser l'API qu'ils utilisent (comme l'exemple ci-dessous)
  • Utilisez un cadre comme Sélénium/WebDriver à naviguer sur le site avec un navigateur entièrement natif.

Pour effectuer l'ingénierie inverse de l'API, les outils de proxy de débogage Web sont inestimables. Vous pouvez obtenir beaucoup d'informations en regardant l'onglet "réseau" des outils de développement du navigateur, mais des choses comme "Fiddler", "Charles Proxy", "Burp", etc. sont inestimables.

Lorsque vous inspectez le trafic, vous verrez les paramètres suivants disponibles pour envoyer votre demande:

  • Page
  • durée
  • person_capacity
  • room_type
  • chargement
  • sw_lat
  • sw_lng
  • ne-Lat
  • ne_lng

Vous pouvez trouver des valeurs valides pour jouer avec en utilisant des choses comme

[37] pry(main)> page.css("[data-room-type]").map{|n| n["data-room-type"]}.uniq 
=> ["entire_home_apt", "private_room", "shared_room"] 

Si vous définissez les différentes valeurs de latitude/lng aux choses qui vous conviennent, vous obtiendrez les prix moyens hebdomadaires pour cette région. Je remarque que "localized_place" signale mon domaine personnel indépendamment du changement de latitude/longitude, mais les valeurs monétaires changent en fait et correspondent à ce que le site montre. Peut-être que cet attribut est basé sur la localisation IP, ou il y a quelque chose qui cloche.

Alors que les valeurs semblent évoluer avec des régions plus grandes et plus petites pour les limites sw/ne, vous pouvez également utiliser les mêmes lat/lng pour les deux et obtenir toujours des résultats. Cela peut ne pas refléter exactement la manière dont Google Geocoder référence un lieu, mais cela pourrait suffire à vos besoins. Une fois que vous avez une source pour obtenir votre lat/lngs, vous pouvez simplement les nourrir directement à leur API.

est ici ce qui semble être un exemple de travail:

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)"}