{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Google Play review collection for one application\n",
        "\n",
        "This annotated copy of the collection notebook demonstrates the one-application procedure used in the study. \n",
        "Set APP_NAME to the application's public-facing name and APP_ID to its Google Play package identifier; run the notebook separately for each of the six applications. \n",
        "APP_NAME labels the exported workbook, while APP_ID controls which application is queried. \n",
        "The example below is configured for Klíč eGovernmentu. \n",
        "\n",
        "The request uses lang='cs' and country='cz'. These are scraper request parameters; the notebook does not independently test the language of each review. \n",
        "A new run retrieves the reviews available at the time of that run and will not recreate the 30 April 2026 snapshot. \n",
        "This notebook exports the returned records for one application. Filtering reviews without text and combining the six application files are separate processing steps.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# BUŇKA 1 — Instalace knihoven (spusť jednou, trvá ~30 sekund)\n!pip install google-play-scraper openpyxl pandas --quiet\nprint('✅ Hotovo')"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# BUŇKA 2 — Stažení recenzí\n\nimport pandas as pd\nimport time\nfrom google_play_scraper import reviews, Sort\n\nAPP_NAME = 'Klíč eGovernmentu'  # public-facing application name\nAPP_ID = 'cz.mojedatovaschranka.mobilniklic'  # Google Play package ID\n\nvsechny_recenze = []\ncontinuation_token = None\nbatch = 0\n\nprint(f'⏳ Downloading reviews for {APP_NAME} ({APP_ID})')\nprint('   (může trvat několik minut)\\n')\n\nwhile True:\n    batch += 1\n\n    result, continuation_token = reviews(\n        APP_ID,\n        lang='cs',\n        country='cz',\n        sort=Sort.NEWEST,\n        count=200,\n        continuation_token=continuation_token\n    )\n\n    if not result:\n        print('\\n✅ Staženo vše — Google Play již nemá další recenze.')\n        break\n\n    vsechny_recenze.extend(result)\n    print(f'   Dávka {batch}: +{len(result)} recenzí (celkem {len(vsechny_recenze)})')\n\n    if continuation_token is None:\n        print('\\n✅ Staženo vše.')\n        break\n\n    time.sleep(1)  # pauza aby nás Google nezablokoval\n\nprint(f'\\n📊 Celkem staženo: {len(vsechny_recenze)} recenzí')"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# BUŇKA 3 — Uložení do Excelu\n# Každá recenze bude celá v jedné buňce, bez ohledu na délku\n\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Alignment, Font, PatternFill\nfrom openpyxl.utils import get_column_letter\n\nSOUBOR = f\"{APP_ID.replace('.', '_')}_reviews.xlsx\"\n\n# Připrav DataFrame\ndf = pd.DataFrame(vsechny_recenze)\n\n# Vyber a přejmenuj relevantní sloupce\ndf = df[['reviewId', 'userName', 'score', 'at', 'content', 'thumbsUpCount', 'replyContent', 'repliedAt', 'appVersion']].copy()\ndf.columns = ['ID recenze', 'Uživatel', 'Hodnocení (1-5)', 'Datum', 'Text recenze', 'Počet líbí', 'Odpověď vývojáře', 'Datum odpovědi', 'Verze aplikace']\n\n# Nahraď None prázdným řetězcem\ndf = df.fillna('')\n\n# Odstraň znaky nového řádku UVNITŘ textu recenze\n# (nahradíme je mezerou — text zůstane čitelný ale nebude rozbíjet buňky)\ndf['Text recenze'] = df['Text recenze'].astype(str).str.replace('\\n', ' ', regex=False).str.replace('\\r', ' ', regex=False)\ndf['Odpověď vývojáře'] = df['Odpověď vývojáře'].astype(str).str.replace('\\n', ' ', regex=False).str.replace('\\r', ' ', regex=False)\n\n# Vytvoř Excel soubor přes openpyxl pro plnou kontrolu formátování\nwb = Workbook()\nws = wb.active\nws.title = \"Recenze\"\n\n# Styl hlavičky\nheader_font = Font(bold=True, color=\"FFFFFF\", name=\"Calibri\", size=11)\nheader_fill = PatternFill(\"solid\", start_color=\"2E75B6\")\nheader_align = Alignment(horizontal=\"center\", vertical=\"center\", wrap_text=True)\n\n# Napiš hlavičku\nfor col_idx, col_name in enumerate(df.columns, 1):\n    cell = ws.cell(row=1, column=col_idx, value=col_name)\n    cell.font = header_font\n    cell.fill = header_fill\n    cell.alignment = header_align\n\nws.row_dimensions[1].height = 30\n\n# Napiš data — každá recenze = 1 řádek, wrap_text=True ale ŽÁDNÉ zalomení řádků v textu\ndata_align_text  = Alignment(vertical=\"top\", wrap_text=True)   # pro text recenze\ndata_align_other = Alignment(vertical=\"top\", wrap_text=False)  # pro ostatní sloupce\n\nfor row_idx, row in enumerate(df.itertuples(index=False), 2):\n    for col_idx, value in enumerate(row, 1):\n        cell = ws.cell(row=row_idx, column=col_idx, value=value)\n        # Sloupec \"Text recenze\" (5) a \"Odpověď vývojáře\" (7) — wrap text\n        if col_idx in (5, 7):\n            cell.alignment = data_align_text\n        else:\n            cell.alignment = data_align_other\n\n# Šířky sloupců\nsirky = [36, 20, 16, 20, 80, 14, 50, 20, 16]\nfor col_idx, sirka in enumerate(sirky, 1):\n    ws.column_dimensions[get_column_letter(col_idx)].width = sirka\n\n# Zmraž první řádek\nws.freeze_panes = \"A2\"\n\n# Přidej souhrný list\nws2 = wb.create_sheet(\"Souhrn\")\nws2[\"A1\"] = \"Application name\"\nws2[\"B1\"] = APP_NAME\nws2[\"A2\"] = \"Google Play package ID\"\nws2[\"B2\"] = APP_ID\nws2[\"A3\"] = \"Downloaded review records\"\nws2[\"B3\"] = len(df)\nws2[\"A4\"] = \"Mean star rating\"\nws2[\"B4\"] = round(df['Hodnocení (1-5)'].astype(float).mean(), 2)\nws2[\"A5\"] = \"Download time\"\nws2[\"B5\"] = pd.Timestamp.now().strftime('%d.%m.%Y %H:%M')\n\nfor col in ['A', 'B']:\n    ws2.column_dimensions[col].width = 30\n\nwb.save(SOUBOR)\nprint(f'✅ Excel uložen jako: {SOUBOR}')\nprint(f'   Počet recenzí: {len(df)}')\nprint(f'   Průměrné hodnocení: {round(df[\"Hodnocení (1-5)\"].astype(float).mean(), 2)} ★')"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# BUŇKA 4 — Stažení souboru do počítače\n",
        "\n",
        "from google.colab import files\n",
        "files.download(SOUBOR)\n",
        "print('⬇️ Stahování zahájeno...')"
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}
