{"id":1748,"date":"2022-07-22T17:21:38","date_gmt":"2022-07-22T15:21:38","guid":{"rendered":"https:\/\/hannes.enjoys.it\/blog\/?p=1748"},"modified":"2022-07-22T18:34:13","modified_gmt":"2022-07-22T16:34:13","slug":"looking-at-the-number-of-concurrent-readers-on-the-suddeutsche-zeitung-articles","status":"publish","type":"post","link":"https:\/\/hannes.enjoys.it\/blog\/2022\/07\/looking-at-the-number-of-concurrent-readers-on-the-suddeutsche-zeitung-articles\/","title":{"rendered":"Looking at the number of &#8220;concurrent&#8221; readers on the S\u00fcddeutsche Zeitung articles"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I scraped the <a href=\"https:\/\/www.sueddeutsche.de\/news\/activevisits\">numbers of live readers per article published by S\u00fcddeutsche Zeitung<\/a> on their website for more than 3 years, never did anything too interesting with it and just decided to stop. Basically they publish a list of stories and their estimated current concurrent number of readers. Meaning you get a timestamp -&gt; story\/URL -&gt; number of current readers. Easy enough and interesting for sure.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1663\" height=\"949\" data-id=\"1756\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15.png\" alt=\"\" class=\"wp-image-1756\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15.png 1663w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-300x171.png 300w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-1024x584.png 1024w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-768x438.png 768w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-1536x877.png 1536w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-624x356.png 624w\" sizes=\"auto, (max-width: 1663px) 100vw, 1663px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1663\" height=\"949\" data-id=\"1753\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13.png\" alt=\"\" class=\"wp-image-1753\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13.png 1663w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-300x171.png 300w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-1024x584.png 1024w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-768x438.png 768w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-1536x877.png 1536w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-624x356.png 624w\" sizes=\"auto, (max-width: 1663px) 100vw, 1663px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1663\" height=\"949\" data-id=\"1752\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06.png\" alt=\"\" class=\"wp-image-1752\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06.png 1663w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-300x171.png 300w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-1024x584.png 1024w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-768x438.png 768w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-1536x877.png 1536w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-624x356.png 624w\" sizes=\"auto, (max-width: 1663px) 100vw, 1663px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Here is how it worked, some results and data for you to build upon. Loads of it is stupid and silly, this is just me dumping it publicly so I can purge it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Database<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For data storage I chose the dumbest and easiest approach because I did not care about efficiency. This was a bit troublesome later when the VPS ran out of space but &#8230; <em>shrug<\/em> &#8230; I cleaned up and resumed without changes. Usually it&#8217;s ok to be lazy. :)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So yeah, data storage: A SQLite database with two tables:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"sql\" class=\"language-sql\">CREATE TABLE visitors_per_url (\n    timestamp TEXT,    -- 2022-01-13 10:58:00\n    visitors INTEGER,  -- 13\n    url TEXT           -- \/wissen\/zufriedenheit-stadt-land-1.5504425\n);\n\nCREATE TABLE visitors_total (\n    timestamp TEXT,    -- 2022-01-13 10:58:00\n    visitors INTEGER   -- 13\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Can you spot the horrible bloating issue? Yeah, when the (same) URLs are stored again and again for each row, that gets big very quickly. Well, I was too lazy to write something smarter and more &#8220;relational&#8221;. Like this it is only marginally better than a CSV file (I used indexes on all the fields as I was playing around&#8230;). Hope you can relate. :o)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Scraping<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#!\/usr\/bin\/env python3\n\nfrom datetime import datetime\nfrom lxml import html\nimport requests\nimport sqlite3\nimport os\n\n# # TODO\n# - store URLs in a separate table and reference them by id, this will significantly reduce size of the db :o)\n#     - more complicated insertion queries though so \u00af\\\\\\_(\u30c4)\\_\/\u00af\n\n# The site updates every 2 minutes, so a job should run every 2 minutes.\n\n# # Create database if not exists\nsql_initialise = \"\"\"\nCREATE TABLE visitors_per_url (timestamp TEXT, visitors INTEGER, url TEXT);\nCREATE TABLE visitors_total (timestamp TEXT, visitors INTEGER);\nCREATE INDEX idx_visitors_per_url_timestamp ON visitors_per_url(timestamp);\nCREATE INDEX idx_visitors_per_url_url ON visitors_per_url(url);\nCREATE INDEX idx_visitors_per_url_timestamp_url ON visitors_per_url(timestamp, url);\nCREATE INDEX idx_visitors_total_timestamp ON visitors_total(timestamp);\nCREATE INDEX idx_visitors_per_url_timestamp_date ON visitors_per_url(date(timestamp));\n\"\"\"\n\nif not os.path.isfile(\"sz.db\"):\n    conn = sqlite3.connect('sz.db')\n    with conn:\n        c = conn.cursor()\n        c.executescript(sql_initialise)\n    conn.close()\n\n# # Current time\n# we don't know how long fetching the page will take nor do we\n# need any kind of super accurate timestamps in the first place\n# so let's truncate to full minutes\n# WARNING: this *floors*, you might get visitor counts for stories\n# that were released almost a minute later! timetravel wooooo!\nnow = datetime.now()\nnow = now.replace(second=0, microsecond=0)\nprint(now)\n\n# # Get the webpage with the numbers\npage = requests.get('https:\/\/www.sueddeutsche.de\/news\/activevisits')\ntree = html.fromstring(page.content)\nentries = tree.xpath('\/\/div[@class=\"entrylist__entry\"]')\n\n# # Extract visitor counts and insert them to the database\n# Nothing smart, fixed paths and indexes. If it fails, we will know the code needs updating to a new structure.\n\ntotal_count = entries[0].xpath('span[@class=\"entrylist__count\"]')[0].text\nprint(total_count)\n\nvisitors_per_url = []\nfor entry in entries[1:]:\n    count = entry.xpath('span[@class=\"entrylist__socialcount\"]')[0].text\n    url = entry.xpath('div[@class=\"entrylist__content\"]\/a[@class=\"entrylist__link\"]')[0].attrib['href']\n    url = url.replace(\"https:\/\/www.sueddeutsche.de\", \"\")  # save some bytes...\n    visitors_per_url.append((now, count, url))\n\nconn = sqlite3.connect('sz.db')\nwith conn:\n    c = conn.cursor()\n    c.execute('INSERT INTO visitors_total VALUES (?,?)', (now, total_count))\n    c.executemany('INSERT INTO visitors_per_url VALUES (?,?,?)', visitors_per_url)\nconn.close()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This ran every 2 minutes with a cronjob.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Plots<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I plotted the data with <a href=\"https:\/\/bokeh.org\/\">bokeh<\/a>, I think because it was easiest to get a color category per URL (&#8230; looking at my plotting script, ugh, I am not sure that was the reason).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#!\/usr\/bin\/env python3\n\nimport os\nimport sqlite3\nfrom shutil import copyfile\nfrom datetime import datetime, date\n\nfrom bokeh.plotting import figure, save, output_file\nfrom bokeh.models import ColumnDataSource\n\n# https:\/\/docs.python.org\/3\/library\/sqlite3.html#sqlite3.Connection.row_factory\ndef dict_factory(cursor, row):\n    d = {}\n    for idx, col in enumerate(cursor.description):\n        d[col[0]] = row[idx]\n    return d\n\ntoday = date.isoformat(datetime.now())\n\nconn = sqlite3.connect('sz.db')\nconn.row_factory = dict_factory\nwith conn:\n    c = conn.cursor()\n    c.execute(\n        \"\"\"\n        SELECT * FROM visitors_per_url\n        WHERE visitors &gt; 100\n        AND date(timestamp) = date('now');\n        \"\"\"\n    )\n\n    ## i am lazy so i group in sql, then parse from strings in python :o)\n    #c.execute('SELECT url, group_concat(timestamp) AS timestamps, group_concat(visitors) AS visitors FROM visitors_per_url GROUP BY url;')\n\n    visitors_per_url = c.fetchall()\nconn.close()\n\n# https:\/\/bokeh.pydata.org\/en\/latest\/docs\/user_guide\/data.html so that the data is available for hover\n\ndata = {\n    \"timestamps\": [datetime.strptime(e[\"timestamp\"], '%Y-%m-%d %H:%M:%S') for e in visitors_per_url],\n    \"visitors\": [e[\"visitors\"] for e in visitors_per_url],\n    \"urls\": [e[\"url\"] for e in visitors_per_url],\n    \"colors\": [f\"#{str(hash(e['url']))[1:7]}\" for e in visitors_per_url]  # lol!\n}\n\nsource = ColumnDataSource(data=data)\n\n# https:\/\/bokeh.pydata.org\/en\/latest\/docs\/gallery\/color_scatter.html\n# https:\/\/bokeh.pydata.org\/en\/latest\/docs\/gallery\/elements.html for hover\n\np = figure(\n    tools=\"hover,pan,wheel_zoom,box_zoom,reset\",\n    active_scroll=\"wheel_zoom\",\n    x_axis_type=\"datetime\",\n    sizing_mode='stretch_both',\n    title=f\"Leser pro Artikel auf sueddeutsche.de: {today}\"\n)\n\n# radius must be huge because of unixtime values maybe?!\np.scatter(\n    x=\"timestamps\", y=\"visitors\", source=source,\n    size=5, fill_color=\"colors\", fill_alpha=1, line_color=None,\n    #legend=\"urls\",\n)\n\n# click_policy does not work, hides everything\n#p.legend.location = \"top_left\"\n#p.legend.click_policy=\"hide\"  # mute is broken too, nothing happens\n\np.hover.tooltips = [\n    (\"timestamp\", \"@timestamps\"),\n    (\"visitors\", \"@visitors\"),\n    (\"url\", \"@urls\"),\n]\n\noutput_file(f\"public\/plot_{today}.html\", title=f\"SZ-Leser {today}\", mode='inline')\nsave(p)\n\nos.remove(\"public\/plot.html\")  # will fail once :o)\ncopyfile(f\"public\/plot_{today}.html\", \"public\/plot.html\")<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Results and findings<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Nothing particularly noteworthy comes to mind. You can see perfectly normal days, you can see a pandemic wrecking havoc, you can see fascists being fascists. I found it interesting to see how you can clearly see when articles were pushed on social media or put on the frontpage (or off).<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" data-id=\"1752\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-1024x584.png\" alt=\"\" class=\"wp-image-1752\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-1024x584.png 1024w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-300x171.png 300w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-768x438.png 768w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-1536x877.png 1536w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06-624x356.png 624w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-06.png 1663w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-08.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" data-id=\"1755\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-08-1024x584.png\" alt=\"\" class=\"wp-image-1755\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-08-1024x584.png 1024w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-08-300x171.png 300w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-08-768x438.png 768w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-08-1536x877.png 1536w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-08-624x356.png 624w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-08.png 1663w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" data-id=\"1756\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-1024x584.png\" alt=\"\" class=\"wp-image-1756\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-1024x584.png 1024w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-300x171.png 300w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-768x438.png 768w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-1536x877.png 1536w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15-624x356.png 624w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2019-07-15.png 1663w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" data-id=\"1753\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-1024x584.png\" alt=\"\" class=\"wp-image-1753\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-1024x584.png 1024w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-300x171.png 300w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-768x438.png 768w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-1536x877.png 1536w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13-624x356.png 624w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-13.png 1663w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-15.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" data-id=\"1754\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-15-1024x584.png\" alt=\"\" class=\"wp-image-1754\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-15-1024x584.png 1024w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-15-300x171.png 300w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-15-768x438.png 768w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-15-1536x877.png 1536w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-15-624x356.png 624w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2020-03-15.png 1663w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2022-02-24.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" data-id=\"1751\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2022-02-24-1024x584.png\" alt=\"\" class=\"wp-image-1751\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2022-02-24-1024x584.png 1024w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2022-02-24-300x171.png 300w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2022-02-24-768x438.png 768w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2022-02-24-1536x877.png 1536w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2022-02-24-624x356.png 624w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/2022-02-24.png 1663w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Data<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/hannes.enjoys.it\/stuff\/sz-leser.db.noindexes.7z\">https:\/\/hannes.enjoys.it\/stuff\/sz-leser.db.noindexes.7z<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/hannes.enjoys.it\/stuff\/sz-leser.plots.7z\">https:\/\/hannes.enjoys.it\/stuff\/sz-leser.plots.7z<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If there is anything broken or missing, that&#8217;s how it is. I did not do any double checks just now. :}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I scraped the numbers of live readers per article published by S\u00fcddeutsche Zeitung on their website for more than 3 years, never did anything too interesting with it and just decided to stop. Basically they publish a list of stories and their estimated current concurrent number of readers. Meaning you get a timestamp -&gt; story\/URL [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[32,18,58],"tags":[],"class_list":["post-1748","post","type-post","status-publish","format-standard","hentry","category-german","category-journalismus","category-scraping"],"_links":{"self":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts\/1748","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/comments?post=1748"}],"version-history":[{"count":10,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts\/1748\/revisions"}],"predecessor-version":[{"id":1770,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts\/1748\/revisions\/1770"}],"wp:attachment":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/media?parent=1748"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/categories?post=1748"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/tags?post=1748"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}