Rubyscript om Google-positie te zien
Gisteren was ik in Amsterdam met Sanne Roemen en Daan Kortenbach, voor een erg leuk gesprek.
We hebben het ook even over zoekmachines gehad, waarbij Daan vertelde dat hij op pagina 1 kwam voor een goed trefwoord. Uiteraard heb ik zelf ook even gekeken of ik op één van de eerste pagina’s kom, wat helaas niet zo is.
Maar dit gaf me wel een idee: het komt best veel voor dat ik even wil weten of ik voor bepaalde trefwoorden in de eerste 3 of 5 pagina’s sta. Nu zijn er natuurlijk programma’s om dit te doen, maar voor mij betekent dit toch meestal het trefwoord intypen in Google en dan pagina 1, 2, 3, 4 en 5 aanklikken, zoeken naar mijn domeinnaam en hopen dat ik er bij sta.
Nu had ik natuurlijk op zoek kunnen gaan naar zo’n programma, maar in plaats daarvan automatiseerde dit proces zelf door een stukje Ruby.
Zoals gewoonlijk beginnen we eerst met de volledige code en gaan we het vervolgens analyseren:
#!/usr/bin/env ruby -w
require 'net/http'
class GooglePage
attr_reader :keyword, :pageNumber, :url, :googleResultPage, :maxPages, :position
def initialize(keyword, url, googleUrl = "www.google.com", maxPages = 10, perPage = 10 )
@keyword = keyword
@googleUrl = googleUrl
#om te voorkomen dat het script niet werkt als mensen de www. vergeten te vermelden in de URL zetten we deze er zelf in
@googleUrl = "www." + googleUrl unless @googleUrl =~ /^www\.$/
@url = url
@perPage = perPage
@maxPages = 2
@pageNumber = 1
end
def checkGoogle
getPage
if @body.include?( @url )
@position = getPosition
return @pageNumber
else
@pageNumber += 1
checkGoogle unless @pageNumber >= @maxPages
end
end
def getPage
@body = ""
Net::HTTP.start( @googleUrl, 80 ) {|http|
start = (@pageNumber - 1) * @perPage
resultPage = "/search?q=#{@keyword.gsub( "\s", "+" )}&start=#{start}"
@googleResultPage = "http://" + @googleUrl + resultPage
req = Net::HTTP::Get.new( resultPage )
@body += http.request( req ).body
}
end
def getPosition
position = 0
@body.scan( /span class=a>(.*?)<\/span>/ ).each{ |w|
position += 1
return position if w[ 0 ] =~ /^#{@url}/
}
end
end
Goed, laten we eens gaan kijken wat dit allemaal betekent.
We beginnen met het maken van een class, GooglePage. Daarna gebruiken we attr_reader, om als het ware automatisch getters te genereren. Waarom dit handig is zullen we later zien.
Met def initialize maken we de constructor aan, deze methode wordt dus aangeroepen als we een nieuw object maken met deze klasse door GooglePage.new.
De rest van deze methode is weinig over te zeggen denk ik, gewoon wat variablen toewijzen lijkt me aardig duidelijk.
De methode checkGoogle wordt al wat spannender. Eerst vragen we de inhoud van de pagina op via getPage (hier over later meer), en daarna kijken we of de opgegeven URL voorkomt in de resultatenpagina. Zo ja, zoeken we de positie binnen de pagina op met getPosition wat ook gelijk de returnvalue is.
Als het niet zo is, gaan we naar de volgende pagina kijken en beginnen we gewoon overnieuw totdat we de site in de resultaten gevonden hebben of we voorbij pagina 10 zijn. Als je niet in de eerste 10 pagina’s staat, is het vaak toch al niet interessant meer. Dit nummer is echter aan te passen bij het aanmaken van het object.
getPage, deze methode opent een connectie met Google.nl en haalt de code op. Eventuele spaties in de keywords worden vervangen met een + om errors te voorkomen.
Ten slotte getPosition. Hier proberen we te bepalen op welke positie op de pagina je ongeveer staat, het is wat buggy (met name als er meer resultaten van één site zijn), maar het geeft wel een indruk of je bovenin of onderin staat. We doen dit door te zoeken naar een bepaald stukje HTML (<span class a>) en de URL binnen deze span te bekijken. Komt deze niet overeen met de URL die we zoeken tellen we 1 op bij de positie en gaan we door tot we ‘m gevonden hebben.
Dan nog even een volledig voorbeeld met een paar leuke keywords genomen en ze in een hash gezet waar we vervolgens één voor één doorheen lopen. Ik zoek naar de URL digicted.nl, en gebruik Google.nl.
#!/usr/bin/env ruby -w
require 'net/http'
class GooglePage
attr_reader :keyword, :pageNumber, :url, :googleResultPage, :maxPages, :position
def initialize(keyword, url, googleUrl = "www.google.com", maxPages = 10, perPage = 10 )
@keyword = keyword
@googleUrl = googleUrl
#om te voorkomen dat het script niet werkt als mensen de www. vergeten te vermelden in de URL zetten we deze er zelf in
@googleUrl = "www." + googleUrl unless @googleUrl =~ /^www\.$/
@url = url
@perPage = perPage
@maxPages = maxPages
@pageNumber = 1
end
def checkGoogle
getPage
if @body.include?( @url )
@position = getPosition
else
@pageNumber += 1
checkGoogle unless @pageNumber >= @maxPages
end
end
def getPage
@body = ""
Net::HTTP.start( @googleUrl, 80 ) {|http|
start = (@pageNumber - 1) * @perPage
resultPage = "/search?q=#{@keyword.gsub( "\s", "+" )}&start=#{start}"
@googleResultPage = "http://" + @googleUrl + resultPage
req = Net::HTTP::Get.new( resultPage )
@body += http.request( req ).body
}
end
def getPosition
position = 0
@body.scan( /span class=a>(.*?)<\/span>/ ).each{ |w|
position += 1
return position if w[ 0 ] =~ /^#{@url}/
}
end
end
["macbook pro review", "ruby", "macbook", "samsung 205bw", "er is er een jarig", "martijn engler", "weblog" ].each do |keyword|
gp = GooglePage.new( keyword, "digicted.nl", "google.nl", 10 )
if gp.checkGoogle
puts "#{gp.url} gevonden op pagina #{gp.pageNumber} (positie #{gp.position}) voor keyword '#{gp.keyword}': #{gp.googleResultPage}"
else
puts "#{gp.url} staat niet in de eerste #{gp.maxPages} pagina's van Google voor het keyword '#{gp.keyword}'"
end
end
De output is op het moment van schrijven als volgt:
digicted.nl gevonden op pagina 1 (positie 6) voor keyword 'macbook pro review': http://www.google.nl/search?q=macbook+pro+review&start=0 digicted.nl staat niet in de eerste 10 pagina's van Google voor het keyword 'ruby' digicted.nl gevonden op pagina 5 (positie 6) voor keyword 'macbook': http://www.google.nl/search?q=macbook&start=40 digicted.nl gevonden op pagina 1 (positie 11) voor keyword 'samsung 205bw': http://www.google.nl/search?q=samsung+205bw&start=0 digicted.nl gevonden op pagina 4 (positie 11) voor keyword 'er is er een jarig': http://www.google.nl/search?q=er+is+er+een+jarig&start=30 digicted.nl gevonden op pagina 1 (positie 1) voor keyword 'martijn engler': http://www.google.nl/search?q=martijn+engler&start=0 digicted.nl staat niet in de eerste 10 pagina's van Google voor het keyword 'weblog'
19-08-2007 13:29
Goed stuk Martijn. Ruby is trouwens enorm leuk spul om mee bezig te zijn. Het draait hier lokaal dan ook op de server..
19-08-2007 19:19
Bedankt Redstar.
Ruby is inderdaad erg leuk!
Jij hebt Rails draaien, neem ik aan? Heb ik nog niet zo heel veel mee gedaan (wel wat mee gespeeld, maar wilde eerst Ruby wat beter onder de knie krijgen toen) - is ook mooi spul.
19-08-2007 19:57
@ Martijn, Ik heb Rails, en sinds kort ook Ruby draaien op aanraden van een vriend die daar een project draait. Het is idd zeer leuk spul om mee bezig te zijn…
19-08-2007 20:12
Alleen is hosting op het moment nog wat lastig geloof ik. Maar dat gaat ook de goede kant op, dus ik denk dat ik een volgend project ook weer ‘ns naar Rails kijk!
22-09-2007 18:12
Hmz. Dat lijkt me een handig scriptje, kan ik toch zien hoe hard afvalzak ownt
Ga hem wel een keer proberen.