Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 为什么我的Ruby函数只抓取第一页而不抓取分页的页面?_Ruby On Rails_Ruby_Web Scraping_Nokogiri_Httparty - Fatal编程技术网

Ruby on rails 为什么我的Ruby函数只抓取第一页而不抓取分页的页面?

Ruby on rails 为什么我的Ruby函数只抓取第一页而不抓取分页的页面?,ruby-on-rails,ruby,web-scraping,nokogiri,httparty,Ruby On Rails,Ruby,Web Scraping,Nokogiri,Httparty,我使用nokogiri在经销商网站上对大约14页的所有车辆进行网络刮取,我遇到的错误是我的代码仅在第一页上运行刮取器14次。我的代码有什么问题 从输出中可以看出,相同的车辆被一次又一次地刮伤,而不是下一页中的新车辆 Ruby版本:2.6.2 scraper.rb: require 'nokogiri' require 'httparty' require 'byebug' def scraper url = "https://w

我使用nokogiri在经销商网站上对大约14页的所有车辆进行网络刮取,我遇到的错误是我的代码仅在第一页上运行刮取器14次。我的代码有什么问题

从输出中可以看出,相同的车辆被一次又一次地刮伤,而不是下一页中的新车辆

Ruby版本:2.6.2

scraper.rb:

    require 'nokogiri'
    require 'httparty'
    require 'byebug'
    
    def scraper
        url = "https://www.example.com/new-vehicles/"
        unparsed_page = HTTParty.get(url)
        parsed_page = Nokogiri::HTML(unparsed_page)
        vehicles = Array.new
        vehicle_listings = parsed_page.css("//div[@class='vehicle list-view new-vehicle publish']") #20 cars
        page = 1
        per_page = vehicle_listings.count  #20
        total = parsed_page.css('span.count').text.to_i #281
        last_page = (total.to_f / per_page.to_f).ceil #14
        while page <= last_page
            pagination_url = "https://www.example.com/new-vehicles/#action=im_ajax_call&perform=get_results&page=#{page}"
            pagination_unparsed_page = HTTParty.get(pagination_url)
            puts pagination_url
            puts "Page: #{page}"
            puts ''
            pagination_parsed_page = Nokogiri::HTML(pagination_unparsed_page)
            pagination_vehicle_listings = pagination_parsed_page.css("//div[@class='vehicle list-view new-vehicle publish']") #20 cars
            pagination_vehicle_listings.each do |vehicle_listing|
                vehicle = {
                    title: vehicle_listing.css('h2')&.text&.gsub("New", '').gsub("2021", '').gsub("With", '').gsub("Navigation", ''),
                    price: vehicle_listing.css('span.price')[0]&.text&.delete('^0-9').to_i,
                    stock_number: vehicle_listing.css('.stock-label')&.text.gsub("Stock #: ", ''),
                    exterior_color: vehicle_listing.css('span.detail-content')[3]&.text,
                    interior_color: vehicle_listing.css('span.detail-content')[4]&.text&.delete('0-9').gsub('MPG', 'unavailable')
                }
                vehicles << vehicle
                    puts "Added #{vehicle[:stock_number]}"
                    puts ""
                end
                page += 1
        end
    byebug
    end
        
scraper
需要“nokogiri”
需要“httparty”
需要“byebug”
def刮刀
url=”https://www.example.com/new-vehicles/"
unparsed_page=HTTParty.get(url)
解析的页面=Nokogiri::HTML(未解析的页面)
车辆=阵列。新
vehicle_listings=parsed_page.css(“//div[@class='vehicle list view new vehicle publish'])20辆车
页码=1
每页=车辆列表.计数#20
总计=已解析的页面.css('span.count').text.to#i#281
最后一页=(总计.至页/每页.至页).ceil#14

而page虽然看起来数据是通过GET请求通过链接加载的,但实际上是通过jQuery通过POST请求加载的。 您可以通过打开浏览器开发工具的“网络”选项卡来验证这一点

如果在浏览器中输入url,则会发出一个请求:

  • 获取初始内容的请求
如果随后单击车辆列表的分页导航中的链接,则

  • URL已更新以包含该页面。注意,它不是作为查询(
    ),而是作为片段(
    #
    )的一部分,该片段从不发送到服务器,而是保留在客户端
  • 请求页面的内容是通过POST请求(通过jQuery)获取的,然后该响应被合并到内容中,看起来像是通过链接获取的
如果您想模拟此POST请求,那么它会稍微复杂一些:

它包含一个nonce,您可以在您必须发送的初始内容(搜索
ajax\u nonce
)中找到它(因此,获取初始内容,刮取nonce,然后将其与POST请求一起发送)

下面是一个带有CURL(替换nonce)的示例,该示例将把第2页的列表重新转换为JSON(即使响应标题说
Content-Type:text/html;charset=UTF-8

curl -X POST https://www.pacificbmw.com/
     -H "Content-Type: application/x-www-form-urlencoded" 
     -d "action=im_ajax_call&perform=get_results&page=2&_nonce=e085e144a19b3b493c7aab9aff479722&_post_id=6&_referer=/new-vehicles/" 
这会回来的

{"results":"
<table class=\ "results_table\">\n
    <tbody>\t\n\n
        <tr class=\ "hidden-xs\">\n
            <td colspan=\ "7\">\n
                <!-- VEHICLE BLOCK -->\n
                <div class=\ "vehicle list-view new
    ....

{“结果”:
\n
\t\n\n
\n
\n
\n

通过使用Watir和一个无头chrome浏览器,我能够刮取所需的数据,该浏览器允许在刮取页面之前运行ajax/javascript代码

    require 'nokogiri'
    require 'httparty'
    require 'byebug'
    require 'watir'
    
    def scraper
        url = "https://www.example.com/new-vehicles/"
        unparsed_page = HTTParty.get(url)
        parsed_page = Nokogiri::HTML(unparsed_page)
        vehicles = Array.new
        vehicle_listings = parsed_page.css("//div[@class='vehicle list-view new-vehicle publish']") #20 cars
        page = 1
        per_page = vehicle_listings.count  #20
        total = parsed_page.css('span.count').text.to_i #281
        last_page = (total.to_f / per_page.to_f).ceil #14
        
        # Create instance of headless chrome called browser
        browser = Watir::Browser.new :chrome, headless: true
        
        while page <= last_page
            pagination_url = "https://www.example.com/new-vehicles/#action=im_ajax_call&perform=get_results&page=#{page}"
            browser.goto(pagination_url)
            pagination_unparsed_page = Nokogiri::HTML(browser.html)
            puts pagination_url
            puts "Page: #{page}"
            puts ''
            pagination_parsed_page = pagination_unparsed_page
            pagination_vehicle_listings = pagination_parsed_page.css("//div[@class='vehicle list-view new-vehicle publish']") #20 cars
            pagination_vehicle_listings.each do |vehicle_listing|
                vehicle = {
                    stock_number: vehicle_listing.css('.stock-label')&.text.gsub("Stock #: ", '')
                }
                vehicles << vehicle
                    puts "Added #{vehicle[:stock_number]}"
                    puts ""
                end
                page += 1
        end
        # Be sure to close the browser
        browser.close
    byebug
    end

scraper
需要“nokogiri”
需要“httparty”
需要“byebug”
需要“watir”
def刮刀
url=”https://www.example.com/new-vehicles/"
unparsed_page=HTTParty.get(url)
解析的页面=Nokogiri::HTML(未解析的页面)
车辆=阵列。新
vehicle_listings=parsed_page.css(“//div[@class='vehicle list view new vehicle publish'])20辆车
页码=1
每页=车辆列表.计数#20
总计=已解析的页面.css('span.count').text.to#i#281
最后一页=(总计.至页/每页.至页).ceil#14
#创建名为browser的无头chrome实例
browser=Watir::browser.new:chrome,headless:true

虽然我不认为有必要提供那么多的输出,但也许您可以将其清理一下?请参见:,重点放在单词minimal上。很高兴您提供了一个完整的/可验证的代码示例,但您真的需要显示所有这些信息来解释问题吗?
external\u c的代码是什么颜色:vehicle_listing.css('span.detail content')…
与此有关?向我们展示12页的详细调试是否有助于解释它?换句话说,您可能已经用大约8行代码和不到5%的调试输出解释了这个问题。进一步回答下面的问题,我想说,这个网站非常难刮。您使用的上述方法将d对于大多数网站来说都很好。这里的问题是分页是通过jQuery/AJAX请求来完成的,而不是通过GET请求中的常规查询参数来完成的。@Pascal很抱歉我在问题中减少了过多的输出。