Я пытаюсь Kimurai Framework для рельсов с устройством
app / models / products_spider.rb
class ProductsSpider < Kimurai::Base
@name = 'products_spider'
@engine = :mechanize
def self.process(url, user)
@start_urls = [url]
self.crawl!
end
def parse(response, url:, data: {})
Rails.logger.info "*** Spider - Start parsing"
Rails.logger.info " url: #{url}"
response.xpath("//div[@class='product floatleft span6 vertical-separator' or @class='product floatleft span6 ']").each do |product|
item = {}
item[:title] = product.css('h2.h-pr-title')&.text&.squish
item[:descr] = product.css('p.product_s_desc')&.text&.squish
item[:url] = URI.parse(url).merge(URI.parse(product.css('h2.h-pr-title a')[0]["href"])).to_s
item[:img_url] = URI.parse(url).merge(URI.parse(product.css('img')[0]["src"])).to_s
item[:price_cents] = product.css('span.PricesalesPrice')&.text.gsub(',', '.').to_f * 100
item[:published] = true
item[:categories] = response.xpath("//ul[@class='breadcrumb']/li[@class='active']/span").text.squish
add_event(:custom, :rec_total)
Product.where(item).first_or_create
if Product.where(item).exists?
add_event(:custom, :rec_exists)
else
Product.create!(item)
add_event(:custom, :rec_new)
end
end
end
end
Внутри разбора я хочу:
- получить current_user (сеанс разработки), или
- каким-то образом я могу передать пользовательскую информацию для анализа, или
- Я могу использовать
parse!
, который может вернуть items
массив, но в этом случае, как я могу знать, если процесс завершился нормально или с ошибками? При использовании crawl!
он возвращает response
, который содержит эту информацию ...
app / controllers / products_controller.rb
class ProductsController < ApplicationController
def scrape
url = 'https://manitaropolio.gr/proionta-manitaria/apoksiramena-manitaria'
flash.now[:notice] = "Scrape Url: #{url}"
response = ProductsSpider.process(url, current_user)
if response[:status] == :completed && response[:error].nil?
flash.now[:notice] = "Completed succesfully (added: #{response[:events][:custom][:rec_new]}, existed: #{response[:events][:custom][:rec_exists]}, total: #{response[:events][:custom][:rec_total]})"
else
flash.now[:alert] = response[:error]
end
rescue StandardError => e
flash.now[:alert] = "Error: #{e}"
end
config / rout.rb
Rails.application.routes.draw do
devise_for :users
resources :products do
match '/scrape', to: 'products#scrape', via: :post, on: :collection
end
root to: "public#home"
end
app / views / products / index. html .erb
<p id="notice"><%= notice %></p>
<h1>Products</h1>
<% if can? :scrape, Product %>
<div class="row">
<div class="col">
<%= button_to 'Scrape', scrape_products_path %>
</div>
<% if @products.size > 0 %>
<div class="col text-right">
<%= "Count: #{@products.count}" %>
<%= " (Total Count: #{Product.count})" if current_user.role?(:admin) %>
</div>
<% end %>
</div>
<% end %>
Есть идеи, как мне это сделать?
Спасибо