└── GoogLinked.rb /GoogLinked.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'rubygems' 4 | require 'nokogiri' 5 | require 'mechanize' 6 | require 'optparse' 7 | 8 | class String 9 | def is_upper? 10 | self == self.upcase 11 | end 12 | def is_lower? 13 | self == self.downcase 14 | end 15 | end 16 | 17 | 18 | class GoogLinked 19 | def initialize(companyname, domain) 20 | @agent = Mechanize.new() 21 | @agent.user_agent = "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2 Gecko/20100115 Firefox/4.6" 22 | @companyname = companyname 23 | @domain = domain 24 | @useragents = [ 25 | "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2 Gecko/20100115 Firefox/3.6", 26 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36", 27 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36", 28 | "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36", 29 | "Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0" 30 | ] 31 | 32 | end 33 | 34 | def run_search() 35 | init = search(@companyname, 0) 36 | pages = get_pages(init) 37 | results = "" 38 | names = [] 39 | 40 | (0..pages).each do |pagen| 41 | # puts "Seaching #{pagen}" 42 | results += search(@companyname, pagen) 43 | 44 | Nokogiri::HTML(results).css(".r").css("a").each do |name| 45 | names.push(name.text) 46 | end 47 | end 48 | 49 | emails = [] 50 | 51 | names.each do |title| 52 | tarr = title.split("-")[0].split("|")[0].split(",")[0].split(" ") 53 | if tarr.length > 2 54 | if tarr[2].length >= 2 55 | if tarr[2][0].is_upper? and tarr[2][1].is_upper? 56 | tarr.delete_at(2) 57 | end 58 | end 59 | end 60 | emails.push(tarr[0].downcase+"."+tarr[-1].downcase+"@"+@domain) 61 | end 62 | 63 | return emails 64 | end 65 | 66 | def get_pages(init) 67 | pages = [] 68 | 69 | Nokogiri::HTML(init).css(".fl").css("a").each do |page| 70 | pages.push(page.text) 71 | end 72 | 73 | return pages[-2].to_i - 2 74 | end 75 | 76 | def search(companyname, page) 77 | search_failed = true 78 | while(search_failed) do 79 | begin 80 | randomize_useragent() 81 | results = @agent.get("https://www.google.co.uk/search?num=100&start=#{page*100}&hl=en&q=site:linkedin.com/in+#{companyname.gsub! " " "+"}").body() 82 | rescue 83 | search_failed = true 84 | else 85 | search_failed = false 86 | return results 87 | end 88 | end 89 | end 90 | 91 | def randomize_useragent() 92 | ua = @useragents.sample 93 | @agent.user_agent = ua 94 | end 95 | end 96 | 97 | 98 | options = {} 99 | optparse = OptionParser.new do|opts| 100 | # Set a banner, displayed at the top 101 | # of the help screen. 102 | opts.banner = "Usage: optparse1.rb [options] file1 file2 ..." 103 | # Define the options, and what they do 104 | options[:output] = nil 105 | opts.on( '-o', '--output FILE', 'Write emails to FILE' ) do|file| 106 | options[:output] = file 107 | end 108 | opts.on('-d', '--domain DOMAIN', 'Domain to search for') do |domain| 109 | options[:domain] = domain 110 | end 111 | opts.on('-c', '--company COMPANY NAME LLC', 'Company name to search for') do |companyname| 112 | options[:companyname] = companyname 113 | end 114 | # This displays the help screen, all programs are 115 | # assumed to have this option. 116 | opts.on( '-h', '--help', 'Display this screen' ) do 117 | puts opts 118 | exit 119 | end 120 | end 121 | 122 | optparse.parse! 123 | 124 | if options[:companyname] != nil and options[:domain] != nil 125 | puts "[+] Beginning search..." 126 | searcher = GoogLinked.new(options[:companyname], options[:domain]) 127 | output = searcher.run_search() 128 | puts "[*] Search complete!" 129 | if options[:output] != nil 130 | filename = options[:output] 131 | out = File.open(filename, "w") 132 | output.each do |email| 133 | out.puts email+"\n" 134 | end 135 | puts "[+] Emails for #{options[:companyname]} saved to #{filename}" 136 | else 137 | puts output 138 | end 139 | end 140 | 141 | --------------------------------------------------------------------------------