Instagram'dan python ile fotoğraf indirme

Bugünkü egzersizimiz basit bir python scriptiyle bir instagram sayfasından fotoğraflarını indirmek.

Öncelikle bilmemiz gereken birkaç bilgi:

  • Bu işleme ingilizce scraping deniyor. Tanımı çok geniş ama en temelinde bir sitenin html'ini indirip içinden bilgi çıkarmaya scraping diyoruz.
  • Scraping yaptığımız durumlar genelde sitelerin bize API (Application Programming İnterface kısa) vermediği durumlar. Instagram API'ı çok kısıtlı ve erişim almak biraz zor. O yüzden kolay yola başvuracağız. Yani scraping.
  • Scraping birkaç şekilde yapılabilir. Biz bugün doğrudan html içinden gerekli veriyi alacağız. Diğer teknikler:
    • Beautifulsoup ile html elementlerini (bileşenlerini) ayrıştırmak (parse etmek)ç
    • Selenium ile test modunda Chrome ya da Firefox çalıştırıp siteyi render ettirip içinden veri çıkarmak.

İlk adım bir virtual environment yaratmak olmalı. BUnun için virtualenv kullanacağız. Paket yoneticisi olarak pip kullanacagiz. Python kurulumu icinde gelmis olmasi gerekiyor. Ve python3 kullanacagiz.

# Eger pip yuklu degilse oncelikle onu yukleyelim. Windows'ta python kuruluysa pip yaninda gelmistir.
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py ; python  get-pip.py

# VIrtualenv kuralim
pip install virtualenv

# Bir tane python3 virtual environment yaratalim
virtualenv -p python3 env

# Bu environmenti aktive edelim
source env/bin/activate

# requests pakedini kuralim
pip install requests

# Kodumuzu yazmaya haziriz

Yeni bir python scripti yaratalim. Linux'taysaniz touch instagram_scraper.py yapabilirsiniz .Windows'ta direk sag tik yeni text dosyasi diyip uzantisni .py yaparak degistirebilirsiniz.

import json
import requests

html = request.get('https://www.instagram.com/instagram/').text
print('Instagramdan cektigim html boyutu: ', len(html))

Ustteki scripti yazip kaydedelim ve bir tur calistirmayi deneyelim: python3 instagram_scraper.py

Eger ki 0'dan daha buyuk bir html boyutu goruyorsaniz dogru yoldasiniz demektir.

Simdi instagram'in dondurdugu html'in icinden json olan kismi alip fotograflarin dogrudan url adreslerini bu json'un icinden alacagiz.

Onun icin window.sharedData'yi almamiz gerekiyor. Boyle bir regular expression isimizi gorur:

<script type="text\/javascript">window._sharedData = (.*?);<\/script>

Ondan sonra json'u dictionary'ye cevirip icinden media node'larini almaliyiz.

imgs = json.loads(match_result)['entry_data']['ProfilePage'][0]['graphql']['user']['edge_owner_to_timeline_media']['edges']

Gerisi kolay, bu imajlarin icinde dogrudan jgeg adresleri var onlari teker teker requests kutuphanesini kullanarak indirecegiz.

response = requests.get(url)
with open(shortcode + '.png', 'wb') as f:
    f.write(response.content)

Butun hepsini toplarsak, kodun tamami:

import json
import requests
import re


html = requests.get('https://www.instagram.com/instagram/').text
print('Instagramdan cektigim html boyutu: ', len(html))

pattern = '<script type="text\/javascript">window._sharedData = (.*?);<\/script>'

match_results = re.findall(pattern, html)
match_result = None

if not match_results:
  print('HTMLde veri yok muhtemelen private profil.')
  exit()
match_result = match_results[0]

imgs = []
try:
  imgs = json.loads(match_result)['entry_data']['ProfilePage'][0]['graphql']['user']['edge_owner_to_timeline_media']['edges']
except Exception as e:
  print('Bisiler yanlis gitti', e)
  exit()

for img in imgs:
  img = img['node']
  if img['__typename'] == 'GraphImage':
    shortcode = img['shortcode']
    url = img['display_url']
    print('Indirilen post: https://instagram.com/p/' + shortcode)
    response = requests.get(url)
    with open(shortcode + '.png', 'wb') as f:
      f.write(response.content)

github'da da tam hali gorulebilir.
https://gist.github.com/hakanu/f81d97c47d6d84d48812385195eca211

Bir sonraki yazida private profillerin resimlerini ve fotograflarini indirmeyi deneyecegiz.

Ondan sonraki yazida da video indirmeyi deneyecegiz.