What exactly IS an API? They’re those things that you copy and paste long strange codes into Screaming Frog for links data on a Site Crawl, right?
I’m here to tell you there’s so much more to them than that – if you’re willing to take just a few little steps. But first, some basics.
What’s an API?
API stands for “application programming interface”, and it’s just the way of… using a thing. Everything has an API. The web is a giant API that takes URLs as input and returns pages.
But special data services like the Moz Links API have their own set of rules. These rules vary from service to service and can be a major stumbling block for people taking the next step.
When Screaming Frog gives you the extra links columns in a crawl, it’s using the Moz Links API, but you can have this capability anywhere. For example, all that tedious manual stuff you do in spreadsheet environments can be automated from data-pull to formatting and emailing a report.
If you take this next step, you can be more efficient than your competitors, designing and delivering your own SEO services instead of relying upon, paying for, and being limited by the next proprietary product integration.
GET vs. POST
Most APIs you’ll encounter use the same data transport mechanism as the web. That means there’s a URL involved just like a website. Don’t get scared! It’s easier than you think. In many ways, using an API is just like using a website.
As with loading web pages, the request may be in one of two places: the URL itself, or in the body of the request. The URL is called the “endpoint” and the often invisibly submitted extra part of the request is called the “payload” or “data”. When the data is in the URL, it’s called a “query string” and indicates the “GET” method is used. You see this all the time when you search:
https://www.google.com/search?q=moz+links+api <-- GET method
When the data of the request is hidden, it’s called a “POST” request. You see this when you submit a form on the web and the submitted data does not show on the URL. When you hit the back button after such a POST, browsers usually warn you against double-submits. The reason the POST method is often used is that you can fit a lot more in the request using the POST method than the GET method. URLs would get very long otherwise. The Moz Links API uses the POST method.
Making requests
A web browser is what traditionally makes requests of websites for web pages. The browser is a type of software known as a client. Clients are what make requests of services. More than just browsers can make requests. The ability to make client web requests is often built into programming languages like Python, or can be broken out as a standalone tool. The most popular tools for making requests outside a browser are curl och wget.
We are discussing Python here. Python has a built-in library called URLLIB, but it’s designed to handle so many different types of requests that it’s a bit of a pain to use. There are other libraries that are more specialized for making requests of APIs. The most popular for Python is called requests. It’s so popular that it’s used for almost every Python API tutorial you’ll find on the web. So I will use it too. This is what “hitting” the Moz Links API looks like:
response = requests.post(endpoint, data=json_string, auth=auth_tuple)
Given that everything was set up correctly (more on that soon), this will produce the following output:
{'next_token': 'JYkQVg4s9ak8iRBWDiz1qTyguYswnj035nqrQ1oIbW96IGJsb2dZgGzDeAM7Rw==',
'results': [{'anchor_text': 'moz',
'external_pages': 7162,
'external_root_domains': 2026}]}
This is JSON data. It’s contained within the response object that was returned from the API. It’s not on the drive or in a file. It’s in memory. So long as it’s in memory, you can do stuff with it (often just saving it to a file).
If you wanted to grab a piece of data within such a response, you could refer to it like this:
response['results'][0]['external_pages']
This says: “Give me the first item in the results list, and then give me the external_pages value from that item.” The result would be 7162.
NOTE: If you’re actually following along executing code, the above line won’t work alone. There’s a certain amount of setup we’ll do shortly, including installing the requests library and setting up a few variables. But this is the basic idea.
JSON
JSON stands for JavaScript Object Notation. It’s a way of representing data in a way that’s easy for humans to read and write. It’s also easy for computers to read and write. It’s a very common data format for APIs that has somewhat taken over the world since the older ways were too difficult for most people to use. Some people might call this part of the “restful” API movement, but the much more difficult XML format is also considered “restful” and everyone seems to have their own interpretation. Consequently, I find it best to just focus on JSON and how it gets in and out of Python.
Python dictionaries
I lied to you. I said that the data structure you were looking at above was JSON. Technically it’s really a Python dictionary or dict datatype object. It’s a special kind of object in Python that’s designed to hold key/value pairs. The keys are strings and the values can be any type of object. The keys are like the column names in a spreadsheet. The values are like the cells in the spreadsheet. In this way, you can think of a Python dict as a JSON object. For example here’s creating a dict in Python:
my_dict = {
"name": "Mike",
"age": 52,
"city": "New York"
}
And here is the equivalent in JavaScript:
var my_json = {
"name": "Mike",
"age": 52,
"city": "New York"
}
Pretty much the same thing, right? Look closely. Key-names and string values get double-quotes. Numbers don’t. These rules apply consistently between JSON and Python dicts. So as you might imagine, it’s easy for JSON data to flow in and out of Python. This is a great gift that has made modern API-work highly accessible to the beginner through a tool that has revolutionized the field of data science and is making inroads into marketing, Jupyter Notebooks.
Flattening data
But beware! As data flows between systems, it’s not uncommon for the data to subtly change. For example, the JSON data above might be converted to a string. Strings might look exactly like JSON, but they’re not. They’re just a bunch of characters. Sometimes you’ll hear it called “serializing”, or “flattening”. It’s a subtle point, but worth understanding as it will help with one of the largest stumbling blocks with the Moz Links (and most JSON) APIs.
Objects have APIs
Actual JSON eller dict objekt har sina egna små API:er för att komma åt data inuti dem. Möjligheten att använda dessa JSON och dict API:er försvinner när data plattas till en sträng, men den kommer att färdas mellan system lättare och när den kommer till andra änden kommer den att "deserialiseras" och API:t kommer tillbaka på det andra systemet.
Data flödar mellan system
Detta är konceptet med bärbar, interoperabel data. När det kallades Electronic Data Interchange (eller EDI) var det en väldigt stor sak. Sedan kom webben och sedan XML och sedan JSON och nu är det bara en normal del av att göra affärer.
Om du är i Python och du vill konvertera en dict till en tillplattad JSON-sträng, gör du följande:
import json my_dict = { "name": "Mike", "age": 52, "city": "New York" } json_string = json.dumps(my_dict)
...som skulle producera följande utdata:
'{"name": "Mike", "age": 52, "city": "New York"}'
Detta ser nästan likadant ut som det ursprungliga diktatet, men om du tittar noga kan du se att enstaka citattecken används runt hela saken. En annan uppenbar skillnad är att du kan radbryta riktiga strukturerade data för läsbarhet utan negativ effekt. Du kan inte göra det så lätt med snören. Det är därför det presenteras allt på en rad i ovanstående utdrag.
Sådan strängande processer görs när data överförs mellan olika system eftersom de inte alltid är kompatibla. Normala textsträngar å andra sidan är kompatibla med nästan allt och kan enkelt skickas på webbförfrågningar. Sådana tillplattade strängar av JSON-data kallas ofta förfrågan.
Anatomi av en begäran
Återigen, här är exempelförfrågan vi gjorde ovan:
response = requests.post(endpoint, data=json_string, auth=auth_tuple)
Nu när du förstår vad variabelnamnet json_string säger dig om dess innehåll, borde du inte bli förvånad över att se att det är så här vi fyller i den variabeln:
data_dict = { "target": "moz.com/blog", "scope": "page", "limit": 1 } json_string = json.dumps(data_dict)
…och innehållet i json_string ser ut så här:
'{"target": "moz.com/blog", "scope": "page", "limit": 1}'
Detta är en av mina viktigaste upptäckter när jag lär mig Moz Links API. Detta är gemensamt med otaliga andra API:er där ute, men gör mig upprörd varje gång eftersom det är så mycket bekvämare att arbeta med strukturerade dikter än tillplattade strängar. De flesta API:er förväntar sig dock att data är en sträng för portabilitet mellan system, så vi måste konvertera den i sista stund innan själva API-anropet inträffar.
Pythonic laddar och dumpar
Nu kanske du undrar i exemplet ovan, vad en dumpning gör mitt i koden. De json.dumps() funktionen kallas en "dumper" eftersom den tar ett Python-objekt och dumpar det i en sträng. De json.loads() funktionen kallas en "loader" eftersom den tar en sträng och laddar den i ett Python-objekt.
Anledningen till vad som verkar vara singular- och pluraloptioner är faktiskt binära och strängalternativ. Om din data är binär använder du json.load() och json.dump(). Om din data är en sträng använder du json.loads() och json.dumps(). S:et står för sträng. Att lämna s av betyder binär.
Låt ingen säga att Python är perfekt. Det är bara det att dess grova kanter inte är överdrivet stötande.
Uppdrag vs jämställdhet
För er som är helt nya inom Python eller programmering i allmänhet, det vi gör när vi träffar API kallas en uppgift. Resultatet av requests.post() tilldelas den namngivna variabeln svar.
response = requests.post(endpoint, data=json_string, auth=auth_tuple)
Vi använder tecknet = för att tilldela värdet på höger sida av ekvationen till variabeln på vänster sida av ekvationen. Variabeln svar är nu en referens till objektet som returnerades från API:et. Uppdrag skiljer sig från jämlikhet. De == tecken används för jämlikhet.
# Detta är tilldelning: a = 1 # a är nu lika med 1 # Detta är likhet: a == 1 # Sant, men förlitar sig på att ovanstående rad har exekveras
POST-metoden
respons = requests.post(endpoint, data=json_string, auth=auth_tuple)
De requests biblioteket har en funktion som kallas posta() det krävs 3 argument. Det första argumentet är URL:en för slutpunkten. Det andra argumentet är data som ska skickas till slutpunkten. Det tredje argumentet är autentiseringsinformationen som ska skickas till slutpunkten.
Nyckelordsparametrar och deras argument
Du kanske märker att några av argumenten till posta() funktion har namn. Namn sätts lika med värden med =-tecknet. Så här definieras Python-funktioner. Det första argumentet är positionellt både för att det kommer först och även för att det inte finns något nyckelord. Nyckelordnade argument kommer efter positionsberoende argument. Tro mig, allt känns vettigt efter ett tag. Vi börjar alla tänka som Guido van Rossum.
def arbitrary_function(argument1, namn=argument2): # gör saker
Namnet i exemplet ovan kallas ett "sökord" och värdena som kommer in på dessa platser kallas "argument". Nu tilldelas argument till variabelnamn direkt i funktionsdefinitionen, så du kan referera till antingen argument1 eller argument2 var som helst i den här funktionen. Om du vill lära dig mer om reglerna för Python-funktioner kan du läsa om dem här.
Ställer in begäran
Okej, så låt oss låta dig göra allt som behövs för det framgång säkerställd ögonblick. Vi har visat den grundläggande begäran:
response = requests.post(endpoint, data=json_string, auth=auth_tuple)
…men vi har inte visat allt som ingår i det. Låt oss göra det nu. Om du följer med och inte har förfrågningsbiblioteket installerat kan du göra det med följande kommando från samma terminalmiljö som du kör Python från:
pip-installationsförfrågningar
Ofta har Jupyter redan förfrågningsbiblioteket installerat, men om det inte gör det kan du installera det med följande kommando inifrån en Notebook-cell:
!pip installationsförfrågningar
Och nu kan vi sätta ihop allt. Det finns bara några få saker här som är nya. Det viktigaste är hur vi tar 2 olika variabler och kombinerar dem till en enda variabel som kallas AUTH_TUPLE. Du måste skaffa din egen ACCESSID och SECRETKEY från Moz.com webbplats.
API:n förväntar sig att dessa två värden ska skickas som en Python-datastruktur som kallas a tupel. En tupel är en lista över värden som inte ändras. Det tycker jag är intressant requests.post() förväntar sig tillplattade strängar för data parameter, men förväntar sig en tupel för auth parameter. Jag antar att det är vettigt, men det här är de subtila sakerna att förstå när man arbetar med API:er.
Här är hela koden:
import json import pprint importförfrågningar # Set Constants ACCESSID = "mozscape-1234567890" # Ersätt med ditt åtkomst-ID SECRETKEY = "1234567890abcdef1234567890abcdef" # Ersätt med din hemliga nyckel Variables endpoint = "https:// lsapi.seomoz.com/v2/anchor_text" data_dict = {"target": "moz.com/blog", "scope": "page", "limit": 1} json_string = json.dumps(data_dict) # Gör Request response = requests.post(endpoint, data=json_string, auth=AUTH_TUPLE) # Skriv ut svaret pprint(response.json())
…som ger ut:
{'next_token': 'JYkQVg4s9ak8iRBWDiz1qTyguYswnj035nqrQ1oIbW96IGJsb2dZgGzDeAM7Rw==',
'results': [{'anchor_text': 'moz',
'external_pages': 7162,
'external_root_domains': 2026}]}
Använder alla versaler för AUTH_TUPLE variabel är en konvention många använder i Python för att indikera att variabeln är en konstant. Det är inget krav, men det är en bra idé att följa konventioner när du kan.
Du kanske märker att jag inte använde alla versaler för slutpunkt variabel. Det är för att anchor_text endpoint är inte en konstant. Det finns ett antal olika slutpunkter som kan ta dess plats beroende på vilken typ av uppslag vi ville göra. Valen är:
-
anchor_text
-
final_redirect
-
globala_toppsidor
-
globala_top_root_domains
-
index_metadata
-
länk_korsning
-
länk_status
-
länkande_rotdomäner
-
länkar
-
top_pages
-
url_metrics
-
användningsdata
Och det leder till Jupyter Notebook som jag förberedde om detta ämne här på Github. Med den här anteckningsboken kan du utöka exemplet jag gav här till någon av de 12 tillgängliga slutpunkterna för att skapa en mängd användbara resultat, som kommer att bli föremål för artiklar som följer.