I've been playing with search engines and for the search API I'm going with Bing; Google limits their free API to 100 queries a day and requires creating a custom search engine. Bing requires signing up and getting an "AppID" but from there it's unlimited. Documentation is, well, Microsoftian: impossible to find and hard to use when you get it, but there's a PDF (!) that explains things pretty well. I decided to do everything on the server rather than being fancy with AJAX; the user has to wait either way and usually wants to leave the current page anyway (that's why he's searching!). This is what I came up with:

<?

$appid = 'your app id here'; // for Bing Search API
$q = $_GET['q'];
if (get_magic_quotes_gpc()) $q = stripslashes($q);
// note that $q is unsafe!
?>

<form method="get" action="">
  <input name="q" type="text" value="<?=htmlentities($q)?>" />
  <input type="submit" value="Search" />
</form>

<?

function sitesearch ($query, $site, $appid, $count=NULL){
  $url = "http://api.search.live.net/json.aspx?AppID=$appid&sources=Web&query=".urlencode("$query site:$site");
  if ($count) $url .= "&web.count=$count";
  $ch = curl_init($url);
  curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);
  $result = curl_exec($ch);
  curl_close($ch);
  return json_decode($result);
}

function showerrors($errors){
  echo "<p>Search Error<p>\n";
  foreach ($errors as $error) echo "<p><a href='{$error->HelpUrl}'>{$error->Message}</a>\n";
}

function showresponse ($q, $total, $results){
  $count = count($results);
  if ($count==0){
    $resultwords = 'No results';
  }else if ($total > $count){
    $resultwords = "More than $count results";
  }else if ($count == 1){
    $resultwords = '1 result';
  }else{
    $resultwords = "$count results";
  }
  echo "<p>$resultwords found for <strong>".htmlentities($q)."</strong></p>\n";
  if ($count == 0) return;
  echo "<dl>\n";
  foreach ($results as $result) echo "<dt><a href='{$result->Url}'>{$result->Title}</a></dt>\n<dd>{$result->Description}</dd>\n";
  echo "</dl>\n";    
}

if ($q){
  // get search results
  $result = sitesearch ($q, $_SERVER['HTTP_HOST'], $appid, 10);
  if ($result->SearchResponse->Errors){
    showerrors($result->SearchResponse->Errors);
  }else{
    showresponse($q, $result->SearchResponse->Web->Total, $result->SearchResponse->Web->Results);
  }
  $searchURL = 'http://www.bing.com/search?q='.urlencode("$q site:{$_SERVER['HTTP_HOST']}");
  echo "<p><a href='$searchURL'>See all results</a><p>\n";
}

The code works, though I have to say that Google's search gives better results. The advantage of a stable API outweighs that, I think. You can see it in action on the home page.

One incredibly stupid thing for Microsoft to miss though: bing.com is not a valid URL; you have to use www.bing.com. Who does that anymore?

3 Comments

  1. bob says:

    This is the first easy solution that works that I have found but what I really need help on is something like this that will work with json on a non php site. I have learned to love to hate php because of all the security issues.

    Would you have any ideas how to do this on an aspx page?

  2. Danny says:

    @Bob:
    Unfortunately I don’t know anything about ASP. Once you have the Bing AppID, you just have to be able to grab a URL with HTTP, which is what I’m doing with curl. I assume ASP has something similar available. Then translate the JSON into a native object to use it. There’s a lot of buzzwords here but only two steps which should be straightforward if you’ve done much developing for the web.
    I’d be curious to see your code if you get it working.
    –Danny

  3. Hacking at 0300 : New Bing API says:

    […] I use Bing for the search box on bililite.com, and it's worked well; simple API, no need to create a custom search engine as with Google. Unfortunately, Microsoft is losing almost half a million dollars an hour on Bing, and they want me to make up the difference. Well, not me alone, but they are going to start charging for using their web services. Fortunately, they are (as of now) providing a free tier of up to 5,000 queries a month, which is far more than I need. […]

Leave a Reply


Warning: Undefined variable $user_ID in /home/public/blog/wp-content/themes/evanescence/comments.php on line 75