Class: MagentoMech
- Inherits:
-
Object
- Object
- MagentoMech
- Defined in:
- lib/magento_remote/magento_mech.rb
Overview
The Mech Driver, interacting with a Magento shop page. Note that the Mech does not keep too much state, you have to care about login etc yourself.
Instance Attribute Summary collapse
-
#pass ⇒ Object
Returns the value of attribute pass.
-
#user ⇒ Object
Returns the value of attribute user.
Class Method Summary collapse
-
.from_config(conf) ⇒ Object
Create Mech from hash Argument conf values :base_uri, :user, :pass.
Instance Method Summary collapse
-
#add_to_cart(product_id, qty) ⇒ Object
Put stuff in the cart.
-
#add_to_cart!(product_id, qty) ⇒ Object
Puts as many items of given product to cart as possible Returns number of items put to cart.
-
#find_product(search_string) ⇒ Object
Search products.
- #find_product_id_from(url) ⇒ Object
-
#get_cart_content ⇒ Object
Get the current carts contents.
-
#initialize(base_uri) ⇒ MagentoMech
constructor
Create Mech with base_uri.
-
#last_order_products ⇒ Object
Get products of last order.
-
#log_to!(file) ⇒ Object
Log to given file (-like object).
-
#login ⇒ Object
Login to webpage.
-
#login_with(username, password) ⇒ Object
Login with given credentials.
-
#scrape_products(start_pid, limit) ⇒ Object
Search/scrape products.
Constructor Details
#initialize(base_uri) ⇒ MagentoMech
Create Mech with base_uri
22 23 24 25 26 27 28 |
# File 'lib/magento_remote/magento_mech.rb', line 22 def initialize base_uri @mech = Mechanize.new #@mech.user_agent = 'Mac Safari' #@mech.user_agent = '' @base_uri = base_uri @mech.agent.allowed_error_codes = [429] end |
Instance Attribute Details
#pass ⇒ Object
Returns the value of attribute pass.
9 10 11 |
# File 'lib/magento_remote/magento_mech.rb', line 9 def pass @pass end |
#user ⇒ Object
Returns the value of attribute user.
8 9 10 |
# File 'lib/magento_remote/magento_mech.rb', line 8 def user @user end |
Class Method Details
.from_config(conf) ⇒ Object
Create Mech from hash Argument conf
values :base_uri, :user, :pass.
14 15 16 17 18 19 |
# File 'lib/magento_remote/magento_mech.rb', line 14 def self.from_config(conf) client = MagentoMech.new(conf[:base_uri]) client.user = conf[:user] client.pass = conf[:pass] client end |
Instance Method Details
#add_to_cart(product_id, qty) ⇒ Object
Put stuff in the cart. Returns true if succeeded, false otherwise.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/magento_remote/magento_mech.rb', line 43 def add_to_cart product_id, qty fail "Empty obligatory parameter" if product_id.nil? || qty.to_i <= 0 url = "#{@base_uri}/checkout/cart/add?product=#{product_id}&qty=#{qty}" # Check the returned page name result_page = @mech.get url # There are multiple reasons of failure: # * product_id unknown # * product out of stock # There are multiple ways to detect failure: # * contains a form with post action ending on product/#{product_id}/ # * title is different (stays at product page when failing) # * no success msg div is shown. # * body has a different class. # # Using the last of these options: # return result_page.search('.catalog-product-view').empty? return !result_page.search('.success-msg span').empty? end |
#add_to_cart!(product_id, qty) ⇒ Object
Puts as many items of given product to cart as possible Returns number of items put to cart.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/magento_remote/magento_mech.rb', line 68 def add_to_cart! product_id, qty # Try to be a bit clever and early find out whether article # is out of stock. if add_to_cart(product_id, qty) # to_i return qty end num_ordered = 0 # Apparently not enough in stock! if qty.to_i > 4 if !add_to_cart(product_id, 1) # out of stock return 0 else num_ordered = 1 qty = qty.to_i - 1 end end while qty.to_i > 0 && !add_to_cart(product_id, qty) qty = qty.to_i - 1 end qty.to_i + num_ordered end |
#find_product(search_string) ⇒ Object
Search products. Arguments
search_string: sku, name or title, urlencoded for get request.
returns [[name1, product_id1, instock?1],[name2, p_id2…]…]
or nil if not found.
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/magento_remote/magento_mech.rb', line 119 def find_product search_string url = relative_url("/catalogsearch/result/index/?limit=all&q=#{search_string}") @mech.get url product_li = @mech.page.search('.equal-height .item') return nil if product_li.empty? products = product_li.map do |product| # Add to cart button is missing if out of stock. = product.search("button") stock = && ![0].nil? # Find product ID from wishlist link. wishlist_link = product.search("ul li a")[0] wishlist_link.attributes['href'].value[/product\/(\d+)/] pid = $1 # Find name from heading. name = product.search('h2')[0].text [name, pid, stock] end return products end |
#find_product_id_from(url) ⇒ Object
145 146 147 148 149 150 |
# File 'lib/magento_remote/magento_mech.rb', line 145 def find_product_id_from url page = @mech.get url r_pid = page.search(".//input[@name='product']")[0][:value] r_name = page.search(".product-name .roundall") [r_pid, r_name.text] end |
#get_cart_content ⇒ Object
Get the current carts contents
94 95 96 97 98 99 100 101 |
# File 'lib/magento_remote/magento_mech.rb', line 94 def get_cart_content cart_page = @mech.get("#{@base_uri}/checkout/cart/") name_links = cart_page.search('td h2 a') names = name_links.map &:text quantities_inputs = cart_page.search('.qty') quantities = quantities_inputs.map {|n| n[:value]} names.zip quantities end |
#last_order_products ⇒ Object
Get products of last order. Arguments returns [[product_name1, product_sku1, qty_ordered1],[name2, sku2…]…]
or empty list if not found.
182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/magento_remote/magento_mech.rb', line 182 def last_order_products orders_url = relative_url("/customer/account/") @mech.get orders_url order_url = @mech.page.search('.a-center a').first.attributes['href'] @mech.get order_url @mech.page.search('tr.border').map do |tr| product_name = tr.children[1].children[0].content product_sku = tr.children[3].children[0].content product_qty = tr.children[7].children[1].content[/\d+/] [product_name, product_sku, product_qty] end end |
#log_to!(file) ⇒ Object
Log to given file (-like object).
31 32 33 34 |
# File 'lib/magento_remote/magento_mech.rb', line 31 def log_to! file puts @mech.log @mech.log = Logger.new file end |
#login ⇒ Object
Login to webpage
37 38 39 |
# File 'lib/magento_remote/magento_mech.rb', line 37 def login login_with @user, @pass end |
#login_with(username, password) ⇒ Object
Login with given credentials
104 105 106 107 108 109 110 111 112 |
# File 'lib/magento_remote/magento_mech.rb', line 104 def login_with username, password login_page = @mech.get("#{@base_uri}/customer/account/login/") form = login_page.form_with(:action => '#', :method => 'POST') form.action = "#{@base_uri}/customer/account/loginPost/" form.fields.find{|f| f.name == 'login[username]'}.value = username form.fields.find{|f| f.name == 'login[password]'}.value = password @mech.submit(form) end |
#scrape_products(start_pid, limit) ⇒ Object
Search/scrape products. Arguments
limit: Maximum number of product_ids to check
start_pid: With which product id to start scraping
returns [[name1, product_id1, instock?1],[name2, p_id2…]…]
or nil if not found.
yielding would be nice
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/magento_remote/magento_mech.rb', line 159 def scrape_products start_pid, limit products = [] limit.times do |idx| url = relative_url("/catalog/product/view/id/#{start_pid + idx + 1}") @mech.get url rescue next #if @mech.response_code product_name = @mech.page.search('.product-name .roundall')[0].text wishlist_link = @mech.page.search(".link-wishlist")[0] wishlist_link.attributes['href'].value[/product\/(\d+)/] pid = $1 products << [product_name, pid] if block_given? yield [product_name, pid] end end return products end |