Skip to content

Instantly share code, notes, and snippets.

@rolisz
Created February 14, 2013 15:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rolisz/4953472 to your computer and use it in GitHub Desktop.
Save rolisz/4953472 to your computer and use it in GitHub Desktop.
IPython notebook cu scraping la notele de la BD, PLF, PS ca sa obtinem toate notele bine organizate la un loc.
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "Note"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": "La \u00eenceput, trebuie s\u0103 introducem \u00een Python datele de anul trecut, pe care le am deja fain frumos \u00eentr-un tabel Excel, doar trebuie s\u0103 \u00eel salvez \u00een format CSV \u0219i apoi cu ajutorul modulului csv \u00eel citesc \u00een Python \u00een 3 linii. Totul se bag\u0103 \u00eentr-un dic\u021bionar care con\u021bine \u0219i grupa c\u0103reia apar\u021bine studentul. Din motive de confiden\u021bialitate, \u0219tergem numele dintre valori, acesta r\u0103m\u00e2n\u00e2nd doar \u00eentre chei \u0219i va fi folosit doar la ad\u0103ugarea de note la alte materii. Ca s\u0103 ne simplific\u0103m un pic via\u021ba mai t\u00e2rziu, \u00eenlocuim liniu\u021bele din nume cu spa\u021bii \u0219i ne sc\u0103p\u0103m de diacritice din nume (folosind un snippet copy-pasted de pe [StackOverflow](http://stackoverflow.com/a/9044621/634697))"
},
{
"cell_type": "code",
"collapsed": false,
"input": "import csv\nimport unicodedata\nfile = 'C:\\\\Users\\\\Roland\\\\Documents\\\\Statistici\\\\note_an1.csv'\nnote = {}\nwith open(file) as csvfile:\n reader = csv.DictReader(csvfile)\n for row in reader:\n row['Nume'] = u''.join(c for c in unicodedata.normalize('NFD', row['Nume'].replace('-',' '))\n if unicodedata.category(c) != 'Mn')\n note[row['Nume'].strip()] = row\n del note[row['Nume'].strip()]['Nume']\nprint(list(note.values())[10:20]) ",
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": "[{'POO': '9', 'Grupa': 'Gr. 217', 'Geometrie': '10', 'SdA': '4', 'Nota AC': '7', 'Nota FP': '9', 'Nota algebra': '7'}, {'POO': '6', 'Grupa': 'Gr. 213', 'Geometrie': '8', 'SdA': '4', 'Nota AC': '4', 'Nota FP': '8', 'Nota algebra': '3'}, {'POO': '5', 'Grupa': 'Gr. 217', 'Geometrie': '7', 'SdA': 'a', 'Nota AC': '4', 'Nota FP': '7', 'Nota algebra': '3'}, {'POO': '6', 'Grupa': 'Gr. 215', 'Geometrie': '9', 'SdA': '4', 'Nota AC': '4', 'Nota FP': '5', 'Nota algebra': '5'}, {'POO': '', 'Grupa': 'Gr. 212', 'Geometrie': '3', 'SdA': 'a', 'Nota AC': '4', 'Nota FP': '6', 'Nota algebra': ''}, {'POO': '', 'Grupa': 'Gr. 217', 'Geometrie': 'A', 'SdA': 'a', 'Nota AC': '4', 'Nota FP': '6', 'Nota algebra': '4'}, {'POO': '4', 'Grupa': 'Gr. 213', 'Geometrie': '5', 'SdA': '4', 'Nota AC': '4', 'Nota FP': '6', 'Nota algebra': ''}, {'POO': '9', 'Grupa': 'Gr. 213', 'Geometrie': '9', 'SdA': '9', 'Nota AC': '7', 'Nota FP': '10', 'Nota algebra': '6'}, {'POO': '2', 'Grupa': 'Gr. 216', 'Geometrie': '4', 'SdA': '4', 'Nota AC': '4', 'Nota FP': '6', 'Nota algebra': '2'}, {'POO': '', 'Grupa': 'Gr. 215', 'Geometrie': 'A', 'SdA': 'a', 'Nota AC': '', 'Nota FP': '0', 'Nota algebra': ''}]\n"
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": "Uit\u00e2ndu-ne peste formatul \u00een care avem restul notelor, observ\u0103m c\u00e2teva chestii: la PS \u0219i la BD avem \u0219i ini\u021biala tat\u0103lui \u00een nume. De aceasta va trebui s\u0103 sc\u0103p\u0103m. La PS numele este scris cu litere mari. \u0218i aceasta va trebui corectat \u0219i f\u0103cut s\u0103 fie scris Capitalizat Corect. La PLF pare a fi cel mai fain, deoarece rezultatele sunt \u00eentr-un tabel HTML bine formatat, la fiecare student este trecut\u0103 grupa \u0219i nota, dar nu sunt trecu\u021bi to\u021bi studen\u021bii, doar cei care au fost prezen\u021bi la cel pu\u021bin un examen. La PS \u0219i la BD \u00een schimb sunt trecu\u021bi to\u021bi studen\u021bii, chiar dac\u0103 au lipsit complet. Unele au diacritice pe nume, al\u021bii nu, a\u0219a c\u0103 va trebui s\u0103 normaliz\u0103m \u0219i aceasta. "
},
{
"cell_type": "code",
"collapsed": false,
"input": "def capitalize_remove_father_name(nume):\n nume = u''.join(c for c in unicodedata.normalize('NFD', nume.replace('-',' '))\n if unicodedata.category(c) != 'Mn').split()\n if len(nume) > 2 and \".\" in nume[1]:\n nume = [nume[0]] + nume[2:]\n return \" \".join([x.capitalize() for x in nume])",
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": "S\u0103 ad\u0103ug\u0103m notele la BD. Cum acestea sunt fiecare \u00eentr-un fi\u0219ier HTML separat, vom parcurge pe r\u00e2nd fiecare fi\u0219ier. Cum notele nu sunt sub forma unui tabel HTML, ci pur \u0219i simplu sunt trecu\u021bi \u00eentre dou\u0103 taguri `pre`, va trebui s\u0103 pars\u0103m manual, cu ni\u0219te regexuri, fiecare linie. Din acest tabel vom extrage \u0219i informa\u021bia legat\u0103 de grupa \u00een care se afl\u0103 studenul \u00een acest an, deoarece unii s-au mai mutat de anul trecut, sau poate chiar avem colegi noi. "
},
{
"cell_type": "code",
"collapsed": false,
"input": "for i in range(1,7):\n file = 'C:\\\\Users\\\\Roland\\\\Documents\\\\Statistici\\\\Rezultate 22'+str(i)+'.htm'\n with open(file) as fisier:\n in_pre = False\n for line in fisier:\n if '</pre>' in line:\n break\n if in_pre:\n reg = re.match(\"^(([^\\W\\d_]|\\.| |-)+)([0-9]+)?\",line)\n if reg:\n gr = reg.groups()\n nume = get_nume(capitalize_remove_father_name(gr[0]))\n try:\n nota = int(gr[2])\n except TypeError:\n nota = 0\n if not nume:\n nume = capitalize_remove_father_name(gr[0])\n note[nume] = {}\n print(nume)\n if 'BD' in note[nume]:\n print(\"erreur BD\",nume)\n note[nume]['BD'] = nota\n note[nume]['Grupa 2'] = '22'+str(i)\n if '<pre>' in line:\n in_pre = True",
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": "Precup Ramona Cosmina\nPurcel Lucian Calin\nCatana Laurentiu Tudor\nFlorea Calin\nHoza Cristian Gabriel\nIovanescu Victor\nMate Adrian George\nOprea Madalina\nFedorov Elisabeta"
},
{
"output_type": "stream",
"stream": "stdout",
"text": "\nRosu Ionut Vladut\n"
}
],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": "Ce face func\u021bia `get_nume`? \u00cencearc\u0103 s\u0103 g\u0103seasc\u0103 corespondentul unui nume \u00eentre cele pe care le avem deja \u00een lista de anul trecut. Se poate \u00eent\u00e2mpla ca unii s\u0103 fi folosit alte 2 nume din 3 (sau acum s\u0103 fi folosit toate 3), se poate ca unii s\u0103 fi folosit \u00eentr-un loc numele loc scris cu liniu\u021b\u0103 \u0219i altundeva f\u0103r\u0103. Uneori se poate s\u0103 apar\u0103 mici typouri \u00een liste. We'll do our best to match them all. \n\nIdeea este urm\u0103toarea: verific\u0103m pentru fiecare nume din lista existent\u0103 (a notelor de anul trecut) dac\u0103 nu cumva este o submul\u021bime a numelui curent sau invers. De exemplu \u201eTudor Ion\u201d este submul\u021bime a lui \u201eIon Tudor Gigel\u201d. Apoi verific\u0103m dac\u0103 primul nume (probabil cel de familie) este la fel. Dac\u0103 da, am g\u0103sit cu mare probabilitate numele din lista veche \u0219i \u00eel return\u0103m. Cu asta am cam rezolvat cazul cu 2 nume din 3 \u00eentr-una din liste \u0219i altfel \u00een cealalt\u0103. \n\nApoi ne folosim de libr\u0103ria `difflib`, care ne furnizeaz\u0103 cel mai apropiat nume de cel curent, cu o similaritate mai mare dec\u00e2t 0.85 (valoare stabilit\u0103 empiric astfel \u00eenc\u00e2t s\u0103 nu avem rezultate gre\u0219ite :D). Cu aceasta am rezolvat problema de typo-uri simple. Toate celelalte cazuri trebuiesc rezolvate \u00een mod diferit, \u00een func\u021bie de unde apel\u0103m, a\u0219a c\u0103 return\u0103m `None` \u0219i \u00een func\u021bia apelant\u0103 vom rezolva cum trebuie problema. La BD, consider\u0103m c\u0103 cei care nu au fost g\u0103si\u021bi pe list\u0103 sunt nou veni\u021bi, a\u0219a c\u0103 \u00eei ad\u0103ug\u0103m la dic\u021bionar \u0219i doar apoi le ad\u0103ug\u0103m nota. "
},
{
"cell_type": "code",
"collapsed": false,
"input": "import difflib,re\n\ndef get_nume(nume):\n if nume == '':\n return None\n if nume in note:\n return nume\n else:\n nume_l = re.split('[ -]', nume)\n loop = [\" \".join(nume_l)]\n for n in sorted(note.keys()):\n split_n = list(filter(bool,re.split('[ -]',n)))\n if set(nume_l) <= set(split_n) or set(split_n) < set(nume_l):\n loop = [\" \".join(split_n),\" \".join(nume_l)]\n break\n if len(loop) > 1 and loop[0].split()[0] == loop[1].split()[0]:\n nume_l = loop[0]\n else:\n closest = difflib.get_close_matches(nume,note.keys(),n=1,cutoff = 0.85)\n if len(closest):\n nume_l = closest[0]\n else:\n return None\n return nume_l",
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": "Next up: PS. *bangs head against desk*. Notele de la 4 grupe sunt \u00een format PDF, iar de la celelalte dou\u0103 \u00een format doc. Cu ajutorul unor [unelte online](http://www.freepdftoword.org/), am reu\u0219it s\u0103 transform PDF-urile \u00een Word, de acolo s\u0103 scot tabelele \u00een Excel \u0219i s\u0103 salvez \u00een format CSV. Grea \u00eei via\u021ba de data miner. "
},
{
"cell_type": "code",
"collapsed": false,
"input": "file = 'C:\\\\Users\\\\Roland\\\\Documents\\\\Statistici\\\\ps.csv'\n\nwith open(file) as fisier:\n reader = csv.DictReader(fisier)\n for row in reader:\n if row['Nume'] == '':\n continue\n nume = capitalize_remove_father_name(row['Nume'])\n nume = get_nume(nume)\n if not nume:\n print('PS',row['Nume'])\n continue\n if 'PS' in note[nume]:\n print(\"erreur PS\",nume,row['Nume'])\n try:\n nota = int(row['Nota'])\n except:\n nota = 0\n note[nume]['PS'] = row['Nota']",
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": "erreur PS Iovanescu Victor IOVANESCU VICTOR\nPS POP REMUS DAN\n"
}
],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {},
"source": "Avem un student lips\u0103 \u0219i unul care apare de dou\u0103 ori (desigur, f\u0103r\u0103 not\u0103 de fiecare dat\u0103). Studentul lips\u0103 nu mai apare niciunde altundeva, a\u0219a c\u0103 \u00eel vom l\u0103sa pe dinafar\u0103, mai ales c\u0103 nici nu are not\u0103. "
},
{
"cell_type": "markdown",
"metadata": {},
"source": "Ultimul pas este de a ad\u0103uga notele la PLF. Notele sunt \u00eentr-un tabel HTML, pe care \u00eel putem copia u\u0219or \u00een Excel, p\u0103str\u0103m doar coloanele cu grupa, nume \u0219i nota final\u0103 \u0219i apoi salv\u0103m \u00een format CSV. \u00cen rest proced\u0103m la fel ca mai \u00eenainte."
},
{
"cell_type": "code",
"collapsed": false,
"input": "file = 'C:\\\\Users\\\\Roland\\\\Documents\\\\Statistici\\\\plf.csv'\nwith open(file) as fisier:\n reader = csv.DictReader(fisier)\n for row in reader:\n if row['Nume prenume'] == '':\n continue\n nume = get_nume(row['Nume prenume'])\n if not nume:\n print('PLF',row['Nume prenume'])\n continue\n if 'PLF' in note[nume]:\n print(\"erreur PLF\",nume,row['Nume prenume'])\n try:\n nota = int(row['Nota'])\n except:\n nota = 0\n note[nume]['PLF'] = nota",
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": "PLF Mircea Ionel\nerreur PLF Muntean Liviu Muntean Radu-Liviu\n"
}
],
"prompt_number": 11
},
{
"cell_type": "markdown",
"metadata": {},
"source": "S\u0103 vedem acuma un mic sample din cum ne arat\u0103 notele \u0219i apoi se ne uit\u0103m c\u00e2te note avem pentru fiecare student, ca s\u0103 ne verific\u0103m un pic. "
},
{
"cell_type": "code",
"collapsed": false,
"input": "list(note.values())[30:50]",
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 13,
"text": "[{'BD': 4,\n 'Geometrie': '6',\n 'Grupa': 'Gr. 215',\n 'Grupa 2': '225',\n 'Nota AC': '6',\n 'Nota FP': '6',\n 'Nota algebra': '4',\n 'PLF': 6,\n 'POO': '8',\n 'PS': '6',\n 'SdA': '5'},\n {'BD': 9,\n 'Geometrie': '9',\n 'Grupa': 'Gr. 213',\n 'Grupa 2': '223',\n 'Nota AC': '9',\n 'Nota FP': '8',\n 'Nota algebra': '6',\n 'PLF': 4,\n 'POO': '9',\n 'PS': '9',\n 'SdA': '6'},\n {'BD': 7,\n 'Geometrie': '10',\n 'Grupa': 'Gr. 211',\n 'Grupa 2': '221',\n 'Nota AC': '8',\n 'Nota FP': '10',\n 'Nota algebra': '5',\n 'PLF': 8,\n 'POO': '7',\n 'PS': '9',\n 'SdA': '5'},\n {'BD': 9,\n 'Geometrie': '10',\n 'Grupa': 'Gr. 211',\n 'Grupa 2': '221',\n 'Nota AC': '9',\n 'Nota FP': '8',\n 'Nota algebra': '8',\n 'PLF': 10,\n 'POO': '9',\n 'PS': '8',\n 'SdA': '8'},\n {'BD': 10,\n 'Geometrie': '10',\n 'Grupa': 'Gr. 211',\n 'Grupa 2': '221',\n 'Nota AC': '10',\n 'Nota FP': '8',\n 'Nota algebra': '10',\n 'PLF': 10,\n 'POO': '10',\n 'PS': '9',\n 'SdA': '9'},\n {'BD': 0,\n 'Geometrie': '8',\n 'Grupa': 'Gr. 212',\n 'Grupa 2': '222',\n 'Nota AC': '4',\n 'Nota FP': '5',\n 'Nota algebra': '3',\n 'PLF': 4,\n 'POO': '',\n 'PS': '',\n 'SdA': '4'},\n {'BD': 0, 'Grupa 2': '225', 'PS': 'Absent'},\n {'Geometrie': 'A',\n 'Grupa': 'Gr. 211',\n 'Nota AC': '',\n 'Nota FP': '',\n 'Nota algebra': '',\n 'POO': '',\n 'SdA': 'a'},\n {'BD': 7,\n 'Geometrie': '10',\n 'Grupa': 'Gr. 212',\n 'Grupa 2': '222',\n 'Nota AC': '4',\n 'Nota FP': '6',\n 'Nota algebra': '6',\n 'PLF': 5,\n 'POO': '6',\n 'PS': '9',\n 'SdA': '4'},\n {'Geometrie': 'A',\n 'Grupa': 'Gr. 216',\n 'Nota AC': '',\n 'Nota FP': '0',\n 'Nota algebra': '',\n 'POO': '',\n 'SdA': 'a'},\n {'BD': 6,\n 'Geometrie': '9',\n 'Grupa': 'Gr. 217',\n 'Grupa 2': '226',\n 'Nota AC': '4',\n 'Nota FP': '3',\n 'Nota algebra': '5',\n 'PLF': 4,\n 'POO': '2',\n 'PS': '6',\n 'SdA': '4'},\n {'BD': 7,\n 'Geometrie': 'a',\n 'Grupa': 'Gr. 213',\n 'Grupa 2': '223',\n 'Nota AC': '4',\n 'Nota FP': '6',\n 'Nota algebra': '6',\n 'PLF': 4,\n 'POO': '7',\n 'PS': '6',\n 'SdA': '4'},\n {'BD': 9,\n 'Geometrie': '9',\n 'Grupa': 'Gr. 215',\n 'Grupa 2': '225',\n 'Nota AC': '8',\n 'Nota FP': '6',\n 'Nota algebra': '6',\n 'PLF': 8,\n 'POO': '6',\n 'PS': '7',\n 'SdA': '6'},\n {'BD': 4,\n 'Geometrie': ' A',\n 'Grupa': 'Gr. 215',\n 'Grupa 2': '225',\n 'Nota AC': '4',\n 'Nota FP': '5',\n 'Nota algebra': '',\n 'POO': '6',\n 'PS': '5',\n 'SdA': 'a'},\n {'BD': 10,\n 'Geometrie': '10',\n 'Grupa': 'Gr. 211',\n 'Grupa 2': '221',\n 'Nota AC': '10',\n 'Nota FP': '10',\n 'Nota algebra': '7',\n 'PLF': 10,\n 'POO': '10',\n 'PS': '9',\n 'SdA': '9'},\n {'Geometrie': 'A',\n 'Grupa': 'Gr. 217',\n 'Nota AC': '4',\n 'Nota FP': '8',\n 'Nota algebra': '2',\n 'POO': '',\n 'SdA': 'a'},\n {'Geometrie': 'A',\n 'Grupa': 'Gr. 215',\n 'Nota AC': '',\n 'Nota FP': '0',\n 'Nota algebra': '',\n 'POO': '',\n 'SdA': 'a'},\n {'BD': 8,\n 'Geometrie': '6',\n 'Grupa': 'Gr. 213',\n 'Grupa 2': '223',\n 'Nota AC': '4',\n 'Nota FP': '7',\n 'Nota algebra': '6',\n 'PLF': 7,\n 'POO': '7',\n 'PS': '4',\n 'SdA': '4'},\n {'Geometrie': 'A',\n 'Grupa': 'Gr. 217',\n 'Nota AC': '',\n 'Nota FP': '',\n 'Nota algebra': '',\n 'POO': '',\n 'SdA': 'a'},\n {'BD': 8,\n 'Geometrie': '6',\n 'Grupa': 'Gr. 216',\n 'Grupa 2': '226',\n 'Nota AC': '5',\n 'Nota FP': '6',\n 'Nota algebra': '4',\n 'PLF': 6,\n 'POO': '',\n 'PS': '6',\n 'SdA': 'a'}]"
}
],
"prompt_number": 13
},
{
"cell_type": "code",
"collapsed": false,
"input": "for key in note.keys():\n if len(note[key]) < 7:\n print(key,note[key])\n",
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": "Catana Laurentiu Tudor {'PS': '4', 'BD': 4, 'Grupa 2': '225'}\nIovanescu Victor {'PLF': 4, 'PS': '', 'BD': 0, 'Grupa 2': '225'}\nMate Adrian George {'PS': 'Absent', 'BD': 0, 'Grupa 2': '225'}\nOprea Madalina {'PLF': 4, 'PS': '4', 'BD': 5, 'Grupa 2': '225'}\nFlorea Calin {'PLF': 6, 'PS': 'Absent', 'BD': 4, 'Grupa 2': '225'}\nRosu Ionut Vladut {'PS': '', 'BD': 0, 'Grupa 2': '226'}\nPrecup Ramona Cosmina {'PLF': 4, 'PS': '4', 'BD': 4, 'Grupa 2': '223'}\nFedorov Elisabeta {'PS': '', 'BD': 0, 'Grupa 2': '226'}\nPurcel Lucian Calin {'PS': 'Absent', 'BD': 0, 'Grupa 2': '224'}\nHoza Cristian Gabriel {'PLF': 4, 'PS': 'Absent', 'BD': 0, 'Grupa 2': '225'}\n"
}
],
"prompt_number": 14
},
{
"cell_type": "markdown",
"metadata": {},
"source": "Dup\u0103 cum ne a\u0219teptam, ace\u0219tia sunt colegi noi (mai pu\u021bin M\u0103d\u0103, care \u0219i-o schimbat numele :D)"
},
{
"cell_type": "markdown",
"metadata": {},
"source": "Tot ce mai r\u0103m\u00e2ne de f\u0103cut acuma este s\u0103 scriem \u00eentr-un fi\u0219ier toate acestea, mai verific\u00e2nd o dat\u0103 c\u0103 scriem numere pentru note \u0219i nu alteceva. "
},
{
"cell_type": "code",
"collapsed": false,
"input": "file = 'C:\\\\Users\\\\Roland\\\\Documents\\\\Statistici\\\\grand.csv'\nwith open(file,\"w\") as fisier:\n header = ['Grupa', 'Grupa 2', 'Nota algebra', 'Nota AC', 'Nota FP', 'SdA', 'Geometrie', 'POO', 'BD', 'PLF', 'PS']\n writer = csv.DictWriter(fisier, fieldnames=header)\n writer.writeheader()\n for row in note:\n for materie in header[2:]:\n if materie not in note[row]:\n note[row][materie] = 0\n try:\n int(note[row][materie])\n except ValueError:\n note[row][materie] = 0\n writer.writerow(note[row])\n",
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 15
},
{
"cell_type": "markdown",
"metadata": {},
"source": "A sample of the grand result:\n"
},
{
"cell_type": "raw",
"metadata": {},
"source": "Grupa,Grupa 2,Nota algebra,Nota AC,Nota FP,SdA,Geometrie,POO,BD,PLF,PS\n\nGr. 217,224,6,5,8,7,9,8,8,7,5\n\nGr. 213,223,2,4,6,0,6,8,6,4,4\n\nGr. 211,221,9,10,10,10,9,10,10,10,10\n\nGr. 216,226,8,7,6,6,9,7,9,8,7"
},
{
"cell_type": "markdown",
"metadata": {},
"source": "Perfect. Gata amestecate, numai bune de analizat. "
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment