Skip to content

Instantly share code, notes, and snippets.

@nitaku
Last active September 29, 2015 15:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nitaku/9809328 to your computer and use it in GitHub Desktop.
Save nitaku/9809328 to your computer and use it in GitHub Desktop.
Tootals
Header set Access-Control-Allow-Origin "*"

Search Tootals to obtain an estimate of the Google results for the given keywords. Compare estimates with the bar chart, then click on a bar to actually search Google.

Please be aware that these are rough estimates of the number of results. Even Google does not compute the real number of pages corresponding to a search, relying instead upon a combination of information obtained by its spiders on single-term frequencies (see this page and this paper for more details).

In my opinion, these numbers are not completely useless. While scientifically inaccurate for many tasks, they could be the best estimate we can get for the entire Web. Google does not certainly cover the whole network, but its spiders could have the best possible knowledge of the big data set formed by all Web pages.

This interface can also be used to run some interesting tests about the meaningfulness of result estimates. By combining search terms like "obama" and "barack" with different Google search operators, one can see that an AND query can return a bigger number of estimated results than a single term search!

Or, you could try to search for "neighbour" and "neighbuor" (misspelled) and see that, due to Google's autocorrect feature, the estimate number of results is the same!

<?php
$q = $_SERVER['QUERY_STRING'];
$page = file_get_contents("http://www.google.com/search?$q");
echo $page;
?>
d3.select('#search_input')
.on 'keyup', () ->
### if ENTER is pressed ###
if d3.event.keyCode == 13 or d3.event.which == 13
do_search(this.value)
do_search = (query) ->
d3.html "google_search.php?q=#{query}", (page) ->
estimate = +(d3.select(page).select('#resultStats').text().replace(/,|\./g, '').match(/\d+/)[0])
results.push {query: query, estimate: estimate}
redraw()
results = []
svg = d3.select('svg')
width = svg[0][0].getBoundingClientRect().width
height = svg[0][0].getBoundingClientRect().height
result_height = 30
redraw = () ->
max = d3.max(results, (d)->d.estimate)
results_r = svg.selectAll('.result')
.data(results)
new_results_r = results_r
.enter().append('a')
.attr('class', 'result')
.attr('transform', (d,i) -> "translate(0, #{(results.length-2-i)*result_height})") # needed for the enter animation
.attr('xlink:href', (d) -> "http://www.google.com/search?q=#{d.query}")
new_results_r
.append('rect')
.attr('height', result_height-2)
new_results_r
.append('text')
.text((d) -> d.query)
.attr('dy', '0.35em')
.attr('y', (result_height-2)/2)
.attr('x', 4)
svg.selectAll('.result > rect')
.transition().duration(600)
.attr('width', (d) -> d.estimate/max*600)
results_r
.transition().delay(600).duration(600)
.attr('transform', (d,i) -> "translate(0, #{(results.length-1-i)*result_height})")
body {
margin-top: 40px;
margin-left: 150px;
}
body > * {
display: block;
}
svg {
margin-top: 12px;
}
.result rect {
fill: #66a8d4;
fill-opacity: 0.5;
}
text {
font-family: sans-serif;
font-size: 12px;
}
@font-face {
font-family: "Catull";
src: url("Catull.ttf");
}
#logo {
font-family: "Catull";
font-size: 84px;
color: #555555;
text-align: center;
width: 600px;
}
input {
width: 600px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Tootals</title>
<link type="text/css" href="index.css" rel="stylesheet"/>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<div id="logo">Tootals</div>
<input type="search" id="search_input"/>
<svg width="810" height="300">
</svg>
</body>
<script src="index.js"></script>
</html>
// Generated by CoffeeScript 1.10.0
(function() {
var do_search, height, redraw, result_height, results, svg, width;
d3.select('#search_input').on('keyup', function() {
/* if ENTER is pressed */
if (d3.event.keyCode === 13 || d3.event.which === 13) {
return do_search(this.value);
}
});
do_search = function(query) {
return d3.html("google_search.php?q=" + query, function(page) {
var estimate;
estimate = +(d3.select(page).select('#resultStats').text().replace(/,|\./g, '').match(/\d+/)[0]);
results.push({
query: query,
estimate: estimate
});
return redraw();
});
};
results = [];
svg = d3.select('svg');
width = svg[0][0].getBoundingClientRect().width;
height = svg[0][0].getBoundingClientRect().height;
result_height = 30;
redraw = function() {
var max, new_results_r, results_r;
max = d3.max(results, function(d) {
return d.estimate;
});
results_r = svg.selectAll('.result').data(results);
new_results_r = results_r.enter().append('a').attr('class', 'result').attr('transform', function(d, i) {
return "translate(0, " + ((results.length - 2 - i) * result_height) + ")";
}).attr('xlink:href', function(d) {
return "http://www.google.com/search?q=" + d.query;
});
new_results_r.append('rect').attr('height', result_height - 2);
new_results_r.append('text').text(function(d) {
return d.query;
}).attr('dy', '0.35em').attr('y', (result_height - 2) / 2).attr('x', 4);
svg.selectAll('.result > rect').transition().duration(600).attr('width', function(d) {
return d.estimate / max * 600;
});
return results_r.transition().delay(600).duration(600).attr('transform', function(d, i) {
return "translate(0, " + ((results.length - 1 - i) * result_height) + ")";
});
};
}).call(this);
body
margin-top: 40px
margin-left: 150px
body > *
display: block
svg
margin-top: 12px
.result rect
fill: #66a8d4
fill-opacity: 0.5
text
font-family: sans-serif
font-size: 12px
@font-face
font-family: "Catull"
src: url("Catull.ttf")
#logo
font-family: "Catull"
font-size: 84px
color: #555
text-align: center
width: 600px
input
width: 600px
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment