При попытке использовать open-uri в ruby, некоторое HTML-содержимое отображается как «Загрузка ...» - PullRequest
0 голосов
/ 26 мая 2018

Я пытаюсь создать программу для сравнения определенной вещи на веб-странице, а затем сравнить ее в другой раз, сейчас я работаю над получением фрагмента информации, который изменится.Но текст, который изменился бы, появляется, если я проверяю элемент на странице, но не если я использую open-uri, он появляется как «Загрузка ...» (см. Рисунок), есть ли способ получить весь текст HTML?

Изображение здесь.

Это текущий код, который у меня есть

contents  = open('https://www.cargurus.com/Cars/l-Used-Mazda-MAZDASPEED6-d841', &:read)

File.open("testing.txt", "w") do |line|
line.puts "\r" + "#{contents}"
end

Любая помощь, чтобы получить Загрузка ..., чтобы перейти кфактический HTML-код был бы удивительным.

Спасибо

Ответы [ 2 ]

0 голосов
/ 26 мая 2018

Проблема

Итак, open uri просто делает HTTP-запросы и дает вам доступ к телу.В этом случае тело HTML.Этот HTML имеет заполнитель для этих данных, который вы видите.Затем этот HTML-код говорит о загрузке некоторого javascript, который будет выполнять другой запрос к серверу для получения данных, и когда данные поступят, он заменит заполнитель реальными данными.Итак, чтобы справиться с этим, вам, в конечном счете, нужно все, что возвращается из того запроса, который делает javascript.

Три решения

Заказывается от моего наименее любимого к моему самому любимому.

  1. Вы можете попробовать оценить JavaScript, чтобы он работал на HTML.Это будет болезненно, поэтому я не рекомендую это делать, но если вы хотите пойти по этому пути, я думаю, что есть драгоценный камень под названием «Рубиновый гонщик» или что-то в этом роде (IIRC, он включает в себя версию 8).
  2. Вы можете запустить веб-браузер, позволить браузеру обрабатывать все cray-cray, а затем запрашивать у браузера html после его обновления.Это то, что делает решение Рахула, и это действительно хорошее решение.Это не мой фаворит, потому что он довольно тяжелый, и вы переведены на информацию, отображаемую в html.Это называется «очистка», и она довольно хрупкая (некоторые дизайнеры перемещают что-то по странице и разрывы сценариев), и информация представлена ​​в формате представления человеком, что означает, что вам обычно приходится выполнять множество мелких операций синтаксического анализа.
  3. Вы можете открыть devtools вашего браузера, перейти на вкладку сети, отфильтровать запросы XHR и перезагрузить страницу.Один из них сделал запрос на получение данных, которые использовались для заполнения заполнителя.Выясните, какой это, и затем вы можете сделать этот запрос самостоятельно.Есть также способы, которые могут быть хрупкими, например, иногда вам нужно иметь правильные куки, и вам часто приходится экспериментировать с тем, что послал браузер, чтобы выяснить, сколько вам нужно (обычно это намного меньше, чем было отправлено, чтоверно для вашего случая). Подсказка: Когда вы делаете это, отдельный запрос данных разбирается и анализируется (т. Е. Сохраните его в файл, а затем, просматривая данные, получите его из файла, а не отправляйте новый запрос каждый раз).время ... таким образом, оно не изменится на вас, и вы не получите ограничение скорости)

Решение # 3

Итак, мне было любопытно, и я попыталсяРешение № 3 сам, и это сработало довольно замечательно, посмотрите:

require 'uri'
require 'net/http'

# build a post request to the URL that the page got the data from
uri = URI 'https://www.cargurus.com/Cars/inventorylisting/ajaxFetchSubsetInventoryListing.action?sourceContext=untrackedExternal_true_0'
req = Net::HTTP::Post.new(uri)

# set some headers
req['origin']        = 'https://www.cargurus.com' # for cross origin requests
req['cache-control'] = 'no-cache'                 # no caching, just in case,
req['pragma']        = 'no-cache'                 # we prob don't want stale data

# looks like you can pass it an awful lot of filters to use
req.set_form_data(
  "page"=>"1", "zip"=>"", "address"=>"", "latitude"=>"", "longitude"=>"",
  "distance"=>"100", "selectedEntity"=>"d841", "transmission"=>"ANY",
  "entitySelectingHelper.selectedEntity2"=>"", "minPrice"=>"", "maxPrice"=>"",
  "minMileage"=>"", "maxMileage"=>"", "bodyTypeGroup"=>"", "serviceProvider"=>"",
  "filterBySourcesString"=>"", "filterFeaturedBySourcesString"=>"",
  "displayFeaturedListings"=>"true", "searchSeoPageType"=>"",
  "inventorySearchWidgetType"=>"AUTO", "allYearsForTrimName"=>"false",
  "daysOnMarketMin"=>"", "daysOnMarketMax"=>"", "vehicleDamageCategoriesRaw"=>"",
  "minCo2Emission"=>"", "maxCo2Emission"=>"", "vatOnly"=>"false",
  "minEngineDisplacement"=>"", "maxEngineDisplacement"=>"", "minMpg"=>"",
  "maxMpg"=>"", "minEnginePower"=>"", "maxEnginePower"=>"", "isRecentSearchView"=>"false"
)

# make the request (200 means it worked)
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request req }
res.code # => "200"

# parse the response
require 'json'
json = JSON.parse res.body

# we're on page 1 of 1, and there are 48 results on this page
json['page']                   # => 1
json['listings'].size          # => 48
json['remainingResults']       # => false

# apparently we're looking at some sort of car or smth
json['modelId']                # => "d841"
json['modelName']              # => "Mazda MAZDASPEED6"

# a bunch of places sell this car
json['sellers'].size           # => 47
json['sellers'][0]['location'] # => "Portland OR, 97217"

# the first of our 48 cars seems to be a deal
listing = json['listings'][0]
listing['mainPictureUrl']        # => "https://static.cargurus.com/images/forsale/2018/05/24/02/58/2006_mazda_mazdaspeed6-pic-61663369386257285-152x114.jpeg"
listing['expectedPriceString']   # => "$8,972"
listing['priceString']           # => "$6,890"
listing['daysOnMarket']          # => 61
listing['savingsRecommendation'] # => "Good Deal"
listing['carYear']               # => 2006
listing['mileageString']         # => "81,803"

# none of the 48 are salvaged or lemons
json['listings'].count { |l| l['lemon'] }   # => 0
json['listings'].count { |l| l['salvage'] } # => 0

# the savings recommendations seem reasonably distributed
json['listings'].group_by { |l| l["savingsRecommendation"] }.map { |rec, ls| [rec, ls.size] }
# => [["Good Deal", 4],
#     ["Fair Deal", 11],
#     ["No Price Analysis", 23],
#     ["High Price", 8],
#     ["Overpriced", 2]]
0 голосов
/ 26 мая 2018

Ваша веб-страница содержит ajax request, а open-uri возвращает только серверную страницу, она не ожидает ajax-запроса

. Вы можете использовать приведенный ниже код, который ожидает загрузки страницы

#load the libraries 
require 'watir'
browser = Watir::Browser.new
browser.goto "https://www.cargurus.com/Cars/l-Used-Mazda-MAZDASPEED6-d841"
# giving some time for website to load
sleep 2
puts browser.html

ПРИМЕЧАНИЕ: вам нужно chromedriver, чтобы использовать скрипт http://chromedriver.chromium.org/downloads, если вы не хотите открывать URL в браузере, тогда вы можете использовать headless-WebKit

...