Cum să răzuiești o listă de subiecte dintr-un subreddit folosind Bash

Reddit pune la dispoziție fluxuri JSON pentru fiecare subreddit. Vă vom arăta cum să creați un script Bash care descarcă și analizează o listă de postări din orice subreddit doriți. Acesta este doar un exemplu de ce puteți face cu fluxurile JSON de la Reddit.

Instalarea Curl și JQ

Vom utiliza `curl` pentru a obține feedul JSON de la Reddit și `jq` pentru a analiza datele JSON și a extrage câmpurile dorite din rezultate. Instalați aceste două dependențe folosind `apt-get` pe Ubuntu și alte distribuții Linux bazate pe Debian. Pe alte distribuții Linux, folosiți instrumentul de gestionare a pachetelor specific distribuției dumneavoastră.

sudo apt-get install curl jq

Descărcarea datelor JSON de la Reddit

Să vedem cum arată fluxul de date. Utilizați `curl` pentru a prelua cele mai recente postări din subredditul MildlyInteresting:

curl -s -A “exemplu de scraper reddit” https://www.reddit.com/r/MildlyInteresting.json

Observați opțiunile folosite înainte de URL: `-s` forțează `curl` să ruleze în mod silențios, astfel încât nu vom vedea nicio ieșire, cu excepția datelor de la serverele Reddit. Următoarea opțiune, `-A „exemplu de scraper reddit”` setează un șir personalizat de user agent, care ajută Reddit să identifice serviciul care accesează datele sale. Serverele Reddit API aplică limite de rată pe baza șirului de user agent. Setarea unei valori personalizate va face ca Reddit să segmenteze limita noastră de rată separat de alți apelanți, reducând șansa de a primi o eroare HTTP 429 (limită de rată depășită).

Rezultatul ar trebui să umple fereastra terminalului și să arate aproximativ așa:

Există o multitudine de câmpuri în datele de ieșire, dar ne interesează doar Titlul, Permalink-ul și URL-ul. Puteți vedea o listă completă a tipurilor și câmpurilor acestora în pagina de documentație API Reddit: https://github.com/reddit-archive/reddit/wiki/JSON

Extragerea datelor din rezultatul JSON

Dorim să extragem Titlul, Permalink-ul și URL-ul din datele de ieșire și să le salvăm într-un fișier delimitat prin tab-uri. Putem folosi instrumente de procesare a textului precum `sed` și `grep`, dar avem la dispoziție un alt instrument care înțelege structurile de date JSON, numit `jq`. Pentru prima încercare, îl vom folosi pentru a tipări și colora rezultatul. Vom folosi același apel ca înainte, dar de data aceasta vom trimite ieșirea prin `jq` și îl vom instrui să analizeze și să tipărească datele JSON.

curl -s -A “exemplu de scraper reddit” https://www.reddit.com/r/MildlyInteresting.json | jq .

Observați punctul care urmează comenzii. Această expresie pur și simplu analizează intrarea și o tipărește așa cum este. Ieșirea arată frumos formatată și colorată:

Să examinăm structura datelor JSON pe care le primim de la Reddit. Rezultatul rădăcină este un obiect care conține două proprietăți: `kind` și `data`. Cea de-a doua deține o proprietate numită `children`, care include o serie de postări din acest subreddit.

Fiecare element din matrice este un obiect care conține, de asemenea, două câmpuri numite `kind` și `data`. Proprietățile pe care vrem să le extragem se află în obiectul `data`. `jq` se așteaptă la o expresie care poate fi aplicată datelor de intrare și produce rezultatul dorit. Trebuie să descriem conținutul în termeni de ierarhie și apartenență la o matrice, precum și modul în care datele ar trebui să fie transformate. Să rulăm din nou întreaga comandă cu expresia corectă:

curl -s -A “exemplu de scraper reddit” https://www.reddit.com/r/MildlyInteresting.json | jq ‘.data.children | .[] | .data.title, .data.url, .data.permalink’

Rezultatul afișează titlul, adresa URL și linkul permanent, fiecare pe propria linie:

Să analizăm în detaliu comanda `jq` pe care am folosit-o:

jq ‘.data.children | .[] | .data.title, .data.url, .data.permalink’

Există trei expresii în această comandă, separate de două simboluri pipe. Rezultatele fiecărei expresii sunt transmise la următoarea pentru evaluare ulterioară. Prima expresie filtrează totul, cu excepția matricei de înregistrări Reddit. Această ieșire este transmisă celei de-a doua expresii și forțată într-o matrice. A treia expresie acționează asupra fiecărui element din matrice și extrage trei proprietăți. Mai multe informații despre `jq` și sintaxa sa pot fi găsite în manualul oficial jq.

Reunirea tuturor într-un script

Să combinăm apelul API și post-procesarea JSON într-un script care va genera un fișier cu postările pe care le dorim. Vom adăuga suport pentru a prelua postările din orice subreddit, nu doar din /r/MildlyInteresting.

Deschideți un editor și copiați conținutul următorului fragment într-un fișier numit `scrape-reddit.sh`:

#!/bin/bash

if [ -z "$1" ]
  then
    echo "Vă rugăm să specificați un subreddit"
    exit 1
fi

SUBREDDIT=$1
NOW=$(date +"%m_%d_%y-%H_%M")
OUTPUT_FILE="${SUBREDDIT}_${NOW}.txt"

curl -s -A "bash-scrape-topics" https://www.reddit.com/r/${SUBREDDIT}.json |
        jq '.data.children | .[] | .data.title, .data.url, .data.permalink' |
        while read -r TITLE; do
                read -r URL
                read -r PERMALINK
                echo -e "${TITLE}t${URL}t${PERMALINK}" | tr --delete '"' >> ${OUTPUT_FILE}
        done

Acest script va verifica mai întâi dacă utilizatorul a furnizat un nume de subreddit. Dacă nu, se va închide cu un mesaj de eroare și un cod de returnare diferit de zero.

Apoi, va stoca primul argument ca nume de subreddit și va construi un nume de fișier marcat cu data în care rezultatul va fi salvat.

Acțiunea începe atunci când `curl` este apelat cu un antet personalizat și URL-ul subreddit-ului de extras. Ieșirea este trimisă către `jq`, unde este analizată și redusă la trei câmpuri: Titlu, URL și Permalink. Aceste linii sunt citite, una câte una, și salvate într-o variabilă folosind comanda `read`, totul într-o buclă `while`, care va continua până când nu mai sunt linii de citit. Ultima linie a blocului interior `while` afișează cele trei câmpuri, delimitate de un caracter tab, apoi le trimite prin comanda `tr`, astfel încât ghilimelele duble să poată fi eliminate. Ieșirea este apoi adăugată la fișier.

Înainte de a putea rula acest script, trebuie să ne asigurăm că i s-au acordat permisiuni de execuție. Utilizați comanda `chmod` pentru a aplica aceste permisiuni fișierului:

chmod u+x scrape-reddit.sh

Și, în final, executați scriptul cu un nume de subreddit:

./scrape-reddit.sh MildlyInteresting

Un fișier de ieșire este generat în același director, iar conținutul său va arăta cam așa:

Fiecare linie conține cele trei câmpuri pe care le urmărim, separate prin caracterul tab.

Ce puteți face în continuare

Reddit este o comoară de conținut și media interesante, toate accesibile cu ușurință folosind API-ul său JSON. Acum că aveți o modalitate de a accesa aceste date și de a procesa rezultatele, puteți face lucruri precum:

Obțineți cele mai recente titluri din /r/WorldNews și trimiteți-le pe desktop folosind notify-send
Integrați cele mai bune glume de pe /r/DadJokes în mesajul zilei al sistemului dumneavoastră.
Obțineți cea mai bună imagine de astăzi de pe /r/aww și setați-o ca fundal al desktopului

Toate acestea sunt posibile folosind datele furnizate și instrumentele pe care le aveți în sistemul dumneavoastră. Spor la experimente!