Skip to content

Commit

Permalink
Merge pull request #632 from takatea/update-example-latest_user_agents
Browse files Browse the repository at this point in the history
More easily update Mechanize::AGENT_ALIASES
  • Loading branch information
flavorjones authored Jan 15, 2024
2 parents 03540ab + 34ccbd6 commit f75af0a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 50 deletions.
89 changes: 49 additions & 40 deletions examples/latest_user_agents.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
require 'mechanize'
require 'ostruct'

# LatestUAFetcher fetches latest user agents from `WhatIsMyBrowser.com`.
# It can use to update `Mechanize::AGENT_ALIASES`.
class LatestUAFetcher
attr_reader :user_agents

USER_AGENT_TYPES = OpenStruct.new(
linux_firefox: "Linux Firefox",
mac_firefox: "Mac Firefox",
mac_safari: "Mac Safari",
windows_chrome: "Windows Chrome",
windows_edge: "Windows Edge",
windows_firefox: "Windows Firefox",
android: "Android",
iphone: "iPhone",
ipad: "iPad",
)

BASE_URL = 'https://www.whatismybrowser.com/guides/the-latest-user-agent'

def initialize
Expand All @@ -11,36 +26,37 @@ def initialize
end

def run
sleep_time = 1

puts 'get chrome UA...'
chrome
puts "sleeping... (#{sleep_time}s)"
sleep 1
return unless user_agents.empty?

puts 'get firefox UA...'
firefox
puts "sleeping... (#{sleep_time}s)"
sleep 1
sleep_time = 1

puts 'get safari UA...'
safari
puts "sleeping... (#{sleep_time}s)"
sleep 1
fetch_user_agents('chrome')
fetch_user_agents('firefox')
fetch_user_agents('safari')
fetch_user_agents('edge')
end

puts 'get edge UA...'
edge
def ordered_user_agents
USER_AGENT_TYPES.to_h.values.each_with_object({}) do |type, ordered_user_agents|
ordered_user_agents[type] = user_agents[type]
end
end

private

def fetch_user_agents(browser_name, sleep_time = 1)
puts "fetch #{browser_name} UA..."
send(browser_name)
puts "sleeping... (#{sleep_time}s)"
sleep sleep_time
end

def edge
page = @agent.get("#{BASE_URL}/edge")

windows_dom = page.css("h2:contains('Latest Edge on Windows User Agents')")
@user_agents[:edge] = {
windows: windows_dom.css('+ .listing-of-useragents .code').first.text
}

@user_agents[USER_AGENT_TYPES.windows_edge] = windows_dom.css('+ .listing-of-useragents .code').first.text
end

def firefox
Expand All @@ -49,11 +65,9 @@ def firefox
desktop_dom = page.css("h2:contains('Latest Firefox on Desktop User Agents')")
table_dom = desktop_dom.css('+ .listing-of-useragents')

@user_agents[:firefox] = {
windows: table_dom.css('td:contains("Windows")').css('+ td .code').text,
macOS: table_dom.css('td:contains("Macos")').css('+ td .code').text,
linux: table_dom.css('td:contains("Linux")').css("+ td .code:contains('Ubuntu; Linux x86_64')").text
}
@user_agents[USER_AGENT_TYPES.linux_firefox] = table_dom.css('td:contains("Linux")').css("+ td .code:contains('Ubuntu; Linux x86_64')").text
@user_agents[USER_AGENT_TYPES.windows_firefox] = table_dom.css('td:contains("Windows")').css('+ td .code').text
@user_agents[USER_AGENT_TYPES.mac_firefox] = table_dom.css('td:contains("Macos")').css('+ td .code').text
end

def safari
Expand All @@ -62,30 +76,25 @@ def safari
macos_dom = page.css("h2:contains('Latest Safari on macOS User Agents')")
ios_dom = page.css("h2:contains('Latest Safari on iOS User Agents')")

@user_agents[:safari] = {
mac_os: macos_dom.css('+ .listing-of-useragents .code').first.text,
iphone: ios_dom.css('+ .listing-of-useragents').css("tr:contains('Iphone') .code").text,
ipad: ios_dom.css('+ .listing-of-useragents').css("tr:contains('Ipad') .code").text
}
@user_agents[USER_AGENT_TYPES.mac_safari] = macos_dom.css('+ .listing-of-useragents .code').first.text
@user_agents[USER_AGENT_TYPES.iphone] = ios_dom.css('+ .listing-of-useragents').css("tr:contains('Iphone') .code").text
@user_agents[USER_AGENT_TYPES.ipad] = ios_dom.css('+ .listing-of-useragents').css("tr:contains('Ipad') .code").text
end

def chrome
page = @agent.get("#{BASE_URL}/chrome")

windows_dom = page.css("h2:contains('Latest Chrome on Windows 10 User Agents')")
linux_dom = page.css("h2:contains('Latest Chrome on Linux User Agents')")
macos_dom = page.css("h2:contains('Latest Chrome on macOS User Agents')")
android_dom = page.css("h2:contains('Latest Chrome on Android User Agents')")

@user_agents[:chrome] = {
windows: windows_dom.css('+ .listing-of-useragents .code').first.text,
linux: linux_dom.css('+ .listing-of-useragents .code').first.text,
mac_os: macos_dom.css('+ .listing-of-useragents .code').first.text,
android: android_dom.css('+ .listing-of-useragents .code').first.text
}
@user_agents[USER_AGENT_TYPES.windows_chrome] = windows_dom.css('+ .listing-of-useragents .code').first.text
@user_agents[USER_AGENT_TYPES.android] = android_dom.css('+ .listing-of-useragents .code').first.text
end
end

agent = LatestUAFetcher.new
agent.run
p agent.user_agents
if $0 == __FILE__
agent = LatestUAFetcher.new
agent.run

pp agent.ordered_user_agents
end
20 changes: 10 additions & 10 deletions lib/mechanize.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class Error < RuntimeError
#
# Windows User-Agent aliases:
#
# * "Windows Chrome"
# * "Windows Edge"
# * "Windows Firefox"
# * "Windows IE 6"
Expand All @@ -127,21 +128,20 @@ class Error < RuntimeError
# agent.user_agent_alias = 'Mac Safari'
#
AGENT_ALIASES = {
# TODO: use output from examples/latest_user_agents.rb as the underling data structure
'Mechanize' => "Mechanize/#{VERSION} Ruby/#{ruby_version} (http://github.com/sparklemotion/mechanize/)",

'Linux Firefox' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:112.0) Gecko/20100101 Firefox/112.0',
'Linux Firefox' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/121.0',
'Linux Konqueror' => 'Mozilla/5.0 (compatible; Konqueror/3; Linux)',
'Linux Mozilla' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624',

'Mac Firefox' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13.3; rv:112.0) Gecko/20100101 Firefox/112.0',
'Mac Firefox' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.2; rv:109.0) Gecko/20100101 Firefox/121.0',
'Mac Mozilla' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4a) Gecko/20030401',
'Mac Safari 4' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; de-at) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10',
'Mac Safari' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15',
'Mac Safari' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15',

'Windows Chrome' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'Windows Edge' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.46',
'Windows Firefox' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:112.0) Gecko/20100101 Firefox/112.0',
'Windows Chrome' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Windows Edge' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.2210.133',
'Windows Firefox' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/121.0',
'Windows IE 6' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
'Windows IE 7' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
'Windows IE 8' => 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
Expand All @@ -150,9 +150,9 @@ class Error < RuntimeError
'Windows IE 11' => 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
'Windows Mozilla' => 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6',

'Android' => 'Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.48 Mobile Safari/537.36',
'iPad' => 'Mozilla/5.0 (iPad; CPU OS 16_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Mobile/15E148 Safari/604.1',
'iPhone' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Mobile/15E148 Safari/604.1',
'Android' => 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.210 Mobile Safari/537.36',
'iPad' => 'Mozilla/5.0 (iPad; CPU OS 17_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1',
'iPhone' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1',
}

AGENT_ALIASES.default_proc = proc { |hash, key|
Expand Down

0 comments on commit f75af0a

Please sign in to comment.