|
| 1 | +--- |
| 2 | +sidebar_position: 1 |
| 3 | +--- |
| 4 | + |
| 5 | +# Introduction |
| 6 | + |
| 7 | +Ferrum is a high-level API to control Chrome in Ruby. |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +It is Ruby clean and high-level API to Chrome. Runs headless by default, but you |
| 12 | +can configure it to run in a headful mode. All you need is Ruby and [Chrome](https://www.google.com/chrome/) or [Chromium](https://www.chromium.org/). |
| 13 | +Ferrum connects to the browser by [CDP protocol](https://chromedevtools.github.io/devtools-protocol/) and there's _no_ |
| 14 | +Selenium/WebDriver/ChromeDriver dependency. The emphasis was made on a raw CDP |
| 15 | +protocol because Chrome allows you to do so many things that are barely |
| 16 | +supported by WebDriver because it should have consistent design with other |
| 17 | +browsers. |
| 18 | + |
| 19 | +## Installation |
| 20 | + |
| 21 | +There's no official Chrome or Chromium package for Linux don't install it this |
| 22 | +way because it's either outdated or unofficial, both are bad. Download it from |
| 23 | +official source for [Chrome](https://www.google.com/chrome/) or [Chromium](https://www.chromium.org/getting-involved/download-chromium). |
| 24 | +Chrome binary should be in the `PATH` or `BROWSER_PATH` and you can pass it as an |
| 25 | +option to browser instance see `:browser_path` in |
| 26 | +[Customization](/docs/ferrum/customization). |
| 27 | + |
| 28 | +Add this to your `Gemfile` and run `bundle install`. |
| 29 | + |
| 30 | +``` ruby |
| 31 | +gem "ferrum" |
| 32 | +``` |
| 33 | + |
| 34 | +## Docker |
| 35 | + |
| 36 | +:::note |
| 37 | +When running in docker as root |
| 38 | +::: |
| 39 | + |
| 40 | +```ruby |
| 41 | +Ferrum::Browser.new(dockerize: true) |
| 42 | +``` |
| 43 | + |
| 44 | +Essentially it just sets CLI flags for a browser to make it start. On CI, you can just set `FERRUM_CHROME_DOCKERIZE=true` environment variable, and it will be |
| 45 | +passed to all browser instances. |
| 46 | + |
| 47 | +## Quick Start |
| 48 | + |
| 49 | +Navigate to a website and save a screenshot: |
| 50 | + |
| 51 | +```ruby |
| 52 | +browser = Ferrum::Browser.new |
| 53 | +browser.go_to("https://google.com") |
| 54 | +browser.screenshot(path: "google.png") |
| 55 | +browser.quit |
| 56 | +``` |
| 57 | + |
| 58 | +When you work with browser instance Ferrum creates and maintains a default page for you, in fact all the methods above |
| 59 | +are sent to the `page` instance that is created in the `default_context` of the `browser` instance. You can interact |
| 60 | +with a page created manually and this is preferred: |
| 61 | + |
| 62 | +```ruby |
| 63 | +browser = Ferrum::Browser.new |
| 64 | +page = browser.create_page |
| 65 | +page.go_to("https://google.com") |
| 66 | +input = page.at_xpath("//input[@name='q']") |
| 67 | +input.focus.type("Ruby headless driver for Chrome", :Enter) |
| 68 | +page.at_css("a > h3").text # => "rubycdp/ferrum: Ruby Chrome/Chromium driver - GitHub" |
| 69 | +browser.quit |
| 70 | +``` |
| 71 | + |
| 72 | +Evaluate some JavaScript and get full width/height: |
| 73 | + |
| 74 | +```ruby |
| 75 | +browser = Ferrum::Browser.new |
| 76 | +page = browser.create_page |
| 77 | +page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara") |
| 78 | +width, height = page.evaluate <<~JS |
| 79 | + [document.documentElement.offsetWidth, |
| 80 | + document.documentElement.offsetHeight] |
| 81 | +JS |
| 82 | +# => [1024, 1931] |
| 83 | +browser.quit |
| 84 | +``` |
| 85 | + |
| 86 | +Do any mouse movements you like: |
| 87 | + |
| 88 | +```ruby |
| 89 | +# Trace a 100x100 square |
| 90 | +browser = Ferrum::Browser.new |
| 91 | +page = browser.create_page |
| 92 | +page.go_to("https://google.com") |
| 93 | +page.mouse |
| 94 | + .move(x: 0, y: 0) |
| 95 | + .down |
| 96 | + .move(x: 0, y: 100) |
| 97 | + .move(x: 100, y: 100) |
| 98 | + .move(x: 100, y: 0) |
| 99 | + .move(x: 0, y: 0) |
| 100 | + .up |
| 101 | + |
| 102 | +browser.quit |
| 103 | +``` |
| 104 | + |
| 105 | +## Clean Up |
| 106 | + |
| 107 | +Closes browser tabs opened by the `Browser` instance. |
| 108 | + |
| 109 | +```ruby |
| 110 | +# connect to a long-running Chrome process |
| 111 | +browser = Ferrum::Browser.new(url: "http://localhost:9222") |
| 112 | + |
| 113 | +browser.go_to("https://github.com/") |
| 114 | + |
| 115 | +# clean up, lest the tab stays there hanging forever |
| 116 | +browser.reset |
| 117 | + |
| 118 | +browser.quit |
| 119 | +``` |
| 120 | + |
| 121 | +## Thread safety |
| 122 | + |
| 123 | +Ferrum is fully thread-safe. You can create one browser or a few as you wish and |
| 124 | +start playing around using threads. Example below shows how to create a few pages |
| 125 | +which share the same context. Context is similar to an incognito profile but you |
| 126 | +can have more than one, think of it like it's independent browser session: |
| 127 | + |
| 128 | +```ruby |
| 129 | +browser = Ferrum::Browser.new |
| 130 | +context = browser.contexts.create |
| 131 | + |
| 132 | +t1 = Thread.new(context) do |c| |
| 133 | + page = c.create_page |
| 134 | + page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara") |
| 135 | + page.screenshot(path: "t1.png") |
| 136 | +end |
| 137 | + |
| 138 | +t2 = Thread.new(context) do |c| |
| 139 | + page = c.create_page |
| 140 | + page.go_to("https://www.google.com/search?q=Ruby+static+typing") |
| 141 | + page.screenshot(path: "t2.png") |
| 142 | +end |
| 143 | + |
| 144 | +t1.join |
| 145 | +t2.join |
| 146 | + |
| 147 | +context.dispose |
| 148 | +browser.quit |
| 149 | +``` |
| 150 | + |
| 151 | +or you can create two independent contexts: |
| 152 | + |
| 153 | +```ruby |
| 154 | +browser = Ferrum::Browser.new |
| 155 | + |
| 156 | +t1 = Thread.new(browser) do |b| |
| 157 | + context = b.contexts.create |
| 158 | + page = context.create_page |
| 159 | + page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara") |
| 160 | + page.screenshot(path: "t1.png") |
| 161 | + context.dispose |
| 162 | +end |
| 163 | + |
| 164 | +t2 = Thread.new(browser) do |b| |
| 165 | + context = b.contexts.create |
| 166 | + page = context.create_page |
| 167 | + page.go_to("https://www.google.com/search?q=Ruby+static+typing") |
| 168 | + page.screenshot(path: "t2.png") |
| 169 | + context.dispose |
| 170 | +end |
| 171 | + |
| 172 | +t1.join |
| 173 | +t2.join |
| 174 | + |
| 175 | +browser.quit |
| 176 | +``` |
| 177 | + |
| 178 | +## Development |
| 179 | + |
| 180 | +After checking out the repo, run `bundle install` to install dependencies. |
| 181 | + |
| 182 | +Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will |
| 183 | +allow you to experiment. |
| 184 | + |
| 185 | +To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the |
| 186 | +version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, |
| 187 | +push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org). |
| 188 | + |
| 189 | + |
| 190 | +## Contributing |
| 191 | + |
| 192 | +Bug reports and pull requests are welcome on [GitHub](https://github.com/rubycdp/ferrum). |
0 commit comments