I do love Instagram and the cool ways we can connect through with, see other cities, people we miss. It’s just hard to deal with having my photos kind of trapped there.
It is possible to export them, but that process takes a while. So this last weekend I took some time to improve a script that I used to extract my photos from there and onto this site.
They are in the pages of the Photos section.
Here is a step by step on what I did for those more tech-inclined.
Some things to take into account before moving on:
This command line tool does the heavy lifting, it authenticates you to Instagram, queries your profile and posts and saves everything to a nice file structure.
What we are going to do is take those files, extract data from them, and save it as environment variables. Those will then be picked up by the Hugo Archetype we defined for new posts in that section.
There are some Hugo functions you can use in these templates, and we are using getenv
that allows us to use environment variables in your new post.
Take a look:
---
categories:
date: {{ getenv "post_datetime"}}
description:
draft: false
resources:
- src: {{ getenv "post_image" }}
name: "header"
layout: instagram
location:
- link: {{ getenv "google_maps_link"}}
- latitude: {{ getenv "latitude" }}
- longitude: {{ getenv "longitude" }}
stories:
subtitle:
title: "{{ getenv "post_title" }}"
tags: {{ getenv "post_tags"}}
---
{{ getenv "post_content" }}
You can tweak this file to add more information, as long as you also do the same in the script that puts it all together. More on that later.
./instagram-posts-from-instaloader.sh setup
./instagram-posts-from-instaloader.sh run-update
Running setup, you will be asked for your username and password. Instaloader will setup a directory with your username where it will store your photos alongside the metadata it found.
We are keeping this directory untouched, read from it, and save the information we need as an environment variable. The full code is below and on GitHub.
Inside the update-post
function we are reading the json data with xzcat
and jq
. If you want to add more data to the exported post, this is where you should look.
After this is done, we check if the post exists and if not, run hugo new ...
and copy any jpg or video files that may be included.
With this done, your new posts should be ready. Run hugo server
to make sure it’s working as you expected.
If you wish to add or improve any bit of the script, feel free to submit a merge request on the GitHub page.
Let me know in the comments if this was useful. 😀
#!/bin/zsh
## USAGE
### 1. Run the setup with `./instagram-posts-from-instaloader.sh setup`
### 2. Execute the update `./instagram-posts-from-instaloader.sh run-update`
## Config
### Where is your blog located?
blog="/Users/brunoamaral/Labs/Digital-Insanity"
### What is your Instagram Username?
instagramUser="brunoamaral"
### Where are we saving the output from Instaloader? (do not include the username)
directoryWithInstagramPosts="/Users/brunoamaral/Labs/instagram/"
### Where do you want photos saved to? Relative to ./content
instagramdir="instagram"
# Dependency check
command -v instaloader >/dev/null 2>&1 || { echo >&2 "I require Instaloader but it's not installed. Aborting."; exit 1 }
command -v xzcat >/dev/null 2>&1 || { echo >&2 "I require xzcat but it's not installed. Aborting."; exit 1 }
command -v jq >/dev/null 2>&1 || { echo >&2 "I require jq but it's not installed. Aborting."; exit 1 }
command -v hugo >/dev/null 2>&1 || { echo >&2 "I require hugo but it's not installed. Aborting."; exit 1 }
setup() {
cd $directoryWithInstagramPosts;
instaloader --fast-update --geotags --login=$instagramUser $instagramUser
}
run-update(){
find "$directoryWithInstagramPosts/$instagramUser" -maxdepth 1 -name '*.json.xz' -exec ./instagram-posts-from-instaloader.sh update-post {} \;
} >&2
update-post() {
file=$(basename $1)
dir=$(dirname $1)
imagefinal=${file//'json.xz'/'jpg'}
content=`xzcat "$1" | jq '.node.edge_media_to_caption.edges[0].node.text'`
declare -a tags;
tags=$(echo $content | grep -o '#[[:alpha:]|[:alnum:]]*')
jsontags=$(printf '%s' "${tags[@]}" | jq -R . | jq -s .)
jsontags=${jsontags//[$'\t\r\n'|$' ']}
jsontags=${jsontags//'#'/}
date=`cut -d'_' -f 1 <<< "$file"`
time=`cut -d'_' -f 2 <<< "$file"`
export post_image=$imagefinal;
export post_datetime=$(echo $date"T"${time//-/:}"+00:00")
export post_tags=$jsontags
if [[ $content = null ]]; then
export post_slug
export post_title=$date
export post_content=" "
else
slug=$(echo "$content" | iconv -c -t ascii//TRANSLIT | sed -E 's/[~\^]+//g' | sed -E 's/[^a-zA-Z0-9]+/-/g' | sed -E 's/^-+\|-+$//g' | sed -E 's/-$//g' | tr A-Z a-z )
export post_slug=${slug:0:25}
title=${content:0:50}
export post_title=${title//'"'}
export post_content=$content
fi
locationfile=${file//.json.xz/_location.txt}
grepLocation=$directoryWithInstagramPosts
grepLocation+="$instagramUser/"$locationfile
location=$(grep -s 'maps.google.com' $grepLocation)
if [[ ! -z "$location" ]]; then
echo "found $location"
export google_maps_link=$location
locationClean=${location/'&ll'/}
export latitude=$(cut -d'=' -f 2 <<< "$locationClean" | cut -d'\' -f 1 | cut -d',' -f 1)
export longitude=$(cut -d'=' -f 2 <<< "$locationClean" | cut -d'\' -f 1 | cut -d',' -f 2)
fi
destination="$blog/content/$instagramdir/$date-$time$post_slug/"
if [[ ! -f "$destination/index.md" ]]; then
hugo new $instagramdir/$date-$time$post_slug/index.md
cp ${1:r:r}(*.jpg|*.mp4) $destination
else
echo 'post exists: '$post_title
fi
} >&2
if [[ $1 = "setup" ]]; then
setup
fi
if [[ $1 = "run-update" ]]; then
run-update
fi
if [[ $1 = "update-post" ]]; then
update-post $2
fi
Enter your email to get a weekly digest of new posts.