I want to take some information about my query from wikipedia using php. I want to have a description, title, img url (if exists), and some side information about it. For example like the google wikipedia information, with much side information.
Until now i have only the description & title.
My code:
$q = str_replace("#", "", ucwords($query));
$opts = array('http' =>
array(
'user_agent' => 'Mozilla Firefox www (http://www.mozilla.org)'
)
);
$context = stream_context_create($opts);
$url = 'en.wikipedia.org/w/api.php?action=opensearch&search='.$q.'&limit=1&namespace=0&format=xml';
#$wiki_arr = simplexml_load_file($url);
if(#$wiki_arr->Section->Item->Text == "" or #strtolower($wiki_arr->Section->Item->Text) != strtolower($q))
{
return "";
}
$title = $wiki_arr->Section->Item->Text;
$description = $wiki_arr->Section->Item->Description;
$url = $wiki_arr->Section->Item->Url;
$result = "".$title.", ".$description.", ".$url."";
Once again, there is no such thing as a Wikipedia API. There is a MediaWiki web API. If something doesn't exist there, it doesn't exist at all in wikipedia.org.
For your question: you said you want to do something like the Wikipedia card in the Google Knowledge Graph. What powers that? Freebase. What's the Wikimedia projects equivalent of Freebase? Wikidata.org. (And not only for Wikipedia, but also for Wikisource etc.) So, please use the Wikidata data, via its API which is documented by itself: http://wikidata.org/w/api.php
You can check the [[wikidata:list of properties]] to know what kind of data to access, and [[mediawikiwiki:Category:Wikibase]] for other libraries to access the API. An example of what you can do this way is wdsearch.js, another reasonator at tools.wmflabs.org (sorry, can't add more links).
Related
PHP Version 7.4
I am currently working on a small php program to take certain shipments and optimize the order of them to the most efficient route. So far so good, it works with the google maps api the following way:
$url = "https://maps.googleapis.com/maps/api/directions/json?";
$url .= "origin=".urlencode($this->startPoint);
$url .= "&destination=".urlencode($this->endPoint);
$url .= "&waypoints=".urlencode("optimize:true")."|";
$x = 0;
foreach($ordersadress as $order){
if($x != 0){
$url .= urlencode("|");
}
$url .= urlencode($order["address"]);
$x++;
}
$url .= "&key=".$conf->global->GOOGLE_MAPS_API_KEY;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = curl_exec($ch);
$json = json_decode($resp);
Now, in order to know which Shipment actually comes first, I go through the json response and compare the addresses of my shipments to each waypoint in the response to see which address comes first and so on.
Here is my problem, in the response the addresses are not written out, they are shortened. For example with a german address, my shipment address that I add to the api call is "Kirchenplatz 4". In googles response they shorten it to "Kirchenpl. 4".
I think the equivalent in english would be changing "Road" to "Rd".
(I will put an example request at the end, incase you do not know what it looks like, you do need a Google API key though.)
For now, I'm doing it the following way:
foreach($json->routes[0]->legs as $leg){
if($iterator != 0){
foreach($ordersadress as $order){
$addy = explode(",", $leg->start_address);
$oa = explode(",", $order["address"]);
//Here I compare if the returned address is the same as the one on the shipment, needs to be a 1:1 match, this is my issue
if(strpos($oa[0], $addy[0]) !== false){
$lat = $leg->start_location->lat;
$lon = $leg->start_location->lng;
$co = $order["object"];
$this->orders[] = ["rowid" => $co->id, "sortorder" => $sortnum, "notes" => "", "tourdate" => $tourdate->format("d.m.Y"), "address" => $leg->start_address, "drivetime" => $leg->duration->value, "object" => $co, "lat" => $lat, "lon" => $lon];
$this->kmAll += round($leg->distance->value/1000, 2);
$sortnum++;
foreach($leg->steps as $step){
$polyline .= $step->polyline->points;
}
break;
}
}
unset($order);
}
This example only works with exact 1:1 matches, which is ofcourse not viable in a real world scenario, as the workers of my customer will not be able to always put the address in the exact same way that google returns it, besides, there is already data for thousands of shipments which would have to be changed.
I have thought of following solutions:
Get a list of all words that are shortened by google, and then do it to my addresses. However I was not able to find a list.
My second solution was to do a percentage match of 2 addresses, and the one with the highest match would be at the position that google returned. With this solution, I am going to be honest I did not really understand the similar_text function and how it works and I am not sure if it would even be a good solution in my case.
I am open to any ideas and suggestions that you might have.
Example Google API request:
https://maps.googleapis.com/maps/api/directions/json?origin=Lange+G.+20%2C+2700+Wiener+Neustadt&destination=Ruckergasse+42%2C+1120+Wien&waypoints=optimize%3Atrue|Brauhausgasse+6%7CHauptpl.+1%2C+Graz%7CKirchenpl.+4%2C+G%C3%A4nserndorf%7CS%C3%BCdtiroler+Pl.+1%2C+Salzburg%7CUnter+dem+Rucker+14%7CVivenotgasse+3%2F6+13%2C+Wien&key=YOUR_API_KEY
After trying for a while and asking some friends I arrived at the solution of using the fuzzy logic to match addresses. Luckily there is already an implementation of a method of this logic which is called levenshtein($string1, $string2)
I would suggest reading it up here: https://www.php.net/manual/de/function.levenshtein.php
Example 1 was basically my solution to the problem and has been working without problems so far.
However be careful! As explained here in the comment below example 1 using UTF-8 will cause problems!
I'm having a hard time using the "link shortening" service in the twitter API
https://dev.twitter.com/docs/tco-link-wrapper/faq
I'm under the impression that a standard type of link should automatically become shortened and clickable when it passes through the API. Yet regardless of how I send the link through, its always as non-clickable text...never shortened, and always counting against the 140 limit.
When using the 1.1 api, how do we direct twitter to deal with URLs?
//this here is simply binary stuff uploaded and posted, using twitteroath library
$media = ss_get_image_binary($file_attachment_path);
$params = array(
'media[]' => "{$media};type=image/jpeg;filename={$file_attachment_path}",
);
$resource_url = 'https://api.twitter.com/1.1/statuses/update_with_media.json';
the link part:
//I'm making my own hashtags, and counting post length stuff myself...
//the backlink variable here is just a typical http: link
$hashtags = ss_make_hastags($tags, $id);
$title = ss_twitter_status_format($image->post_title, $hashtags);
$backlink = get_permalink($id);
$params['status'] = $backlink . ' ' . $hashtags;
//lastly, everything is posted to twitter
$connection = ss_twitter_communication_setup();
$tweet = $connection->post($resource_url, $params);
The image and status are posting fine. The links never become "active" or clickable. And they count against the 140 limit.
one more thing --
This is the class that everything leads back to, setting up communication
$connection = new TwitterOAuth($cons_key, $cons_secret, $oauth_token, $oauth_token_secret);
Found the problem:
LOCALHOST does not work.
facepalm
Begginer here, people. Could anybody suggest any kind of solution? I've an user inputed text.
First of all I check if the text has any urls:
$post = preg_replace('/https?:\/\/[\w\-\.!~?&+\*\'"(),\/]+/','<a class="post_link"
href="$0">$0</a>',$post);
And after that I need to retrieve that url and put as a variable($url) to this function:
$short=make_bitly_url('$url','o_6sgltp5sq4as','R_f5212f1asdads1cee780eed00d2f1bd2fd794f','xml');
And finally, echo both url and user's text. Thanks in advance for ideas and critiques.
I've tried something like that:
$post = preg_replace('/https?:\/\/[\w\-\.!~?&+\*\'"(),\/]+/e',$url,$post){
$shorten = make_bitly_url($url,'o_6sgltpmm5sq4','R_f5212f11cee780ekked00d2f1bd2fd794f','json');
return '<a class="post_link" href="$shorten">$shorten</a>';
};
But even for me it looks some kind of nonsense.
Bitly does have an API available for use. You should check out API Documentation
Here's how to use the bit.ly API from PHP:
/* make a URL small */
function make_bitly_url($url,$login,$appkey,$format = 'xml',$version = '2.0.1')
{
//create the URL
$bitly = 'http://api.bit.ly/shorten?version='.$version.'&longUrl='.urlencode($url).'&login='.$login.'&apiKey='.$appkey.'&format='.$format;
//get the url
//could also use cURL here
$response = file_get_contents($bitly);
//parse depending on desired format
if(strtolower($format) == 'json')
{
$json = #json_decode($response,true);
return $json['results'][$url]['shortUrl'];
}
else //xml
{
$xml = simplexml_load_string($response);
return 'http://bit.ly/'.$xml->results->nodeKeyVal->hash;
}
}
/* usage */
$short = make_bitly_url('http://davidwalsh.name','davidwalshblog','R_96acc320c5c423e4f5192e006ff24980','json');
echo 'The short URL is: '.$short;
// returns: http://bit.ly/11Owun
Source: David Walsh article
HOWEVER, if you wanted to create your own URL shortening system (similar to bit.ly -- and surprisingly easy to do), here is an 8-part tutorial from PHPacademy on how to do that:
Difficulty level: beginner / intermediate
Each video is approx ten minutes.
Part 1
Part 2
Part 3
Part 4
Part 5
Part 6
Part 7
Part 8
Im trying to perform a simple call using ebays search API, when I make a call I get no response, and the problem is with the actual call itself.
$endpoint = 'http://open.api.ebay.com/shopping?';
$responseEncoding = 'XML';
$version = '631'; // API version number
$appID = 'asdf3e6e3';
$itemType = "AllItemTypes";
$itemSort = "EndTime";
//find items advanced
$apicalla = "$endpoint"
."callname=FindItemsAdvanced"
."&version=$version"
."&siteid=0"
."&appid=$appID"
."&MaxEntries=10"
."&ItemSort=EndTime"
."&ItemType=AllItemTypes"
."&IncludeSelector=SearchDetails"
."&responseencoding=$responseEncoding";
$resp = simplexml_load_file($apicalla);
this call is the equivalent to
http://open.api.ebay.com/shopping?callname=FindItemsAdvanced&version=631&siteid=0&appid=asdf3e6e3&MaxEntries=10&ItemSort=EndTime&ItemType=AllItemTypes&IncludeSelector=SearchDetails&responseencoding=XML
My question is what am I missing to make this simple search call?
It looks like you're trying to use eBay's Shopping API, specifically the FindItemsAdvanced call which I believe was deprecated quite some time ago and may no longer be functional (I no longer see it in the call reference). What you want to do is use use findItemsAdvanced from eBay's Finding API.
First, you'll need to change your API endpoint & query string parameters a bit (see the aforementioned findItemsAdvanced call reference for the specifics, but I believe it'll look more like this (I haven't touched my findItemsAdvanced calls in at least 6 months, so I haven't tested this):
$endpoint = 'http://svcs.ebay.com/services/search/FindingService/v1?';
$responseEncoding = 'XML';
$version = '1.8.0'; // API version number (they're actually up to 1.11.0 at this point
$appID = 'asdf3e6e3';
$itemSort = "EndTimeSoonest";
//find items advanced
$apicalla = "$endpoint"
."OPERATION-NAME=findItemsAdvanced"
."&SERVICE-VERSION=$version"
."&GLOBAL-ID=EBAY-US"
."&SECURITY-APPNAME=$appID"
//."&MaxEntries=10" // look for an equivalent for this (maybe paginationInput.entriesPerPage?)
."&sortOrder=EndTimeSoonest"
//."&ItemType=AllItemTypes" // not needed AFAICT, otherwise look at itemFilterType
."&descriptionSearch=true";
."& RESPONSE-DATA-FORMAT=$responseEncoding";
$resp = simplexml_load_file($apicalla);
In addition to this, to use findItemsAdvanced, you must specify what you're searching for either by category (categoryId) or by keywords (keywords), hence the "Please specify a query!" error message.
So, you also need to add something like the following (assuming keywords):
$keywords = "something";
$apicalla .= "&keywords=" . urlencode($keywords);
Giving you the following:
$endpoint = 'http://svcs.ebay.com/services/search/FindingService/v1?';
$responseEncoding = 'XML';
$version = '1.8.0'; // API version number (they're actually up to 1.11.0 at this point
$appID = 'asdf3e6e3';
$itemSort = "EndTimeSoonest";
$keywords = "something"; // make sure this is a valid keyword or keywords
//find items advanced
$apicalla = "$endpoint"
."OPERATION-NAME=findItemsAdvanced"
."&SERVICE-VERSION=$version"
."&GLOBAL-ID=EBAY-US"
."&SECURITY-APPNAME=$appID"
//."&MaxEntries=10" // look for an equivalent for this (maybe paginationInput.entriesPerPage?)
."&sortOrder=$itemSort"
//."&ItemType=AllItemTypes" // not needed AFAICT, otherwise look at itemFilterType
."&descriptionSearch=true";
."& RESPONSE-DATA-FORMAT=$responseEncoding"
."&keywords=" . urlencode($keywords);
$resp = simplexml_load_file($apicalla);
One final note: If you want to load further details of specific items that you find in your results, you'll still want to use the Shopping API (specifically the GetSingleItem & GetMultipleItems calls). So, you may ultimately use a mix of the Shopping & Finding APIs.
It should be something like:
<?php
$url = 'http://svcs.ebay.com/services/search/FindingService/v1?OPERATION-NAME=findItemsAdvanced&SERVICE-VERSION=1.11.0&SECURITY-APPNAME=YOUR_APP_ID&RESPONSE-DATA-FORMAT=XML&REST-PAYLOAD&paginationInput.entriesPerPage=2&keywords=ipod&siteid=203&GLOBAL-ID=EBAY-IN';
$xml = file_get_contents( $url );
$xml = simplexml_load_string( $url );
?>
Log-in to your ebay developer account and click on this link: Test your calls with API Test Tool
Hope this helps.
I have a web application where I'm having the user log into youtube to authorize my web application to access their account. However, I need their youtube user name to actually list their uploaded videos, and I want to ensure that the youtube username they provide matches up with the account they used to authorize with. In other words, I only want the user to be able to share videos that they've uploaded, and not someone else's. Is there a way to do this?
I had done this before with C# .Net with the following code:
YouTubeRequestSettings yt_settings = new YouTubeRequestSettings(<devID name>, devKey, auth);
YouTubeRequest yt_request = new YouTubeRequest(yt_settings);
Uri uri = new Uri("http://gdata.youtube.com/feeds/api/users/default/uploads/?start-index=1&max-results=1");
Feed<Video> videoFeed = yt_request.Get<Video>(uri);
string uploader = "";
if (videoFeed.Entries.Count() > 0)
uploader = videoFeed.Entries.ElementAt(0).Uploader;
But when I try something similar with php I get what appears to be a standard feed:
$yt = new Zend_Gdata_YouTube($http_client,<devID name>,null,$_yt_dev_key);
$feed_url = urlencode("http://gdata.youtube.com/feeds/api/users/default/uploads/?start-index=1&max-results=1");
$videoFeed = $yt->getVideoFeed();
if(count($videoFeed) > 0)
{
$videoEntry = $videoFeed[0];
echo var_dump($videoEntry);
}
Anyone have any idea if I'm doing something wrong?
------------------ UPDATE ----------------------
I have the solution to getting youtube video feed for the user in the authenticated session. $videoFeed = $yt->getuserFeed("default");
Though, I'm still looking at how to get the uploader name from this so that I can perform further video listings directly from javascript (like I had done with my old C#/Asp .Net web app).
----------- A RATHER ROUGH SOLUTION ------------
Well, this isn't exactly an elegant solution, but it's what I have working.
The following will extract the youtube username from a VideoEntry object...
$videoFeed = $yt->getuserUploads("default");
if(count($videoFeed) > 0)
{
$videoEntry = $videoFeed[0];
$v_dump = var_export($videoEntry, true);
$check_for = "http://gdata.youtube.com/feeds/api/users/";
$pos = strpos($v_dump,$check_for);
$start_pos = $pos + strlen($check_for);
$user_name = "";
for($i = $start_pos; $i < strlen($v_dump); $i++)
{
if(($v_dump[$i] == '/') or ($v_dump[$i] == '?'))
break;
$user_name .= $v_dump[$i];
}
echo $user_name;
}
Basically, I'm parsing through the entire video entry variable string representation for the first generic part of the feed url, then getting the next token in the url which is the username. In other words, I'm locating this url in the var dump and parsing the username out:
http://gdata.youtube.com/feeds/api/users/<username>/uploads
If anyone can find a better and cleaner way to do it, that'd be awesome. Parsing a large string like this seems to be a very dirty way of doing this.
See http://code.google.com/apis/youtube/2.0/developers_guide_php.html#Enabling_user_interaction
It says,
Note: Using the string default instead of a username retrieves the profile of the currently authenticated user.
So you can get all the user data about the currently authenticated user using this.
Hope it helps!
Try this:
$user = $yt->getUserProfile('default');
$username = $user->getUserName();