{"id":11249,"date":"2016-03-27T19:50:55","date_gmt":"2016-03-27T17:50:55","guid":{"rendered":"https:\/\/tuxproject.de\/blog\/?p=11249"},"modified":"2024-08-08T16:35:10","modified_gmt":"2024-08-08T14:35:10","slug":"mit-common-lisp-gegen-webmuell","status":"publish","type":"post","link":"https:\/\/tuxproject.de\/blog\/2016\/03\/mit-common-lisp-gegen-webmuell\/","title":{"rendered":"Mit Com\u00admon Lisp gegen Web\u00adm\u00fcll"},"content":{"rendered":"<p>Im Novem\u00adber 2015 <a href=\"https:\/\/tuxproject.de\/blog\/2015\/11\/mit-feed43-gegen-webmuell\/\">schrieb ich<\/a>, der kosten\u00adlo\u00adse Web\u00addienst <a href=\"http:\/\/feed43.com\/\">feed43<\/a> sei zum Ent\u00adm\u00fcl\u00adlen von Web\u00adsites mit\u00adtels RSS prin\u00adzi\u00adpi\u00adell geeig\u00adnet, <em>ver\u00adschlucke<\/em> sich aber gele\u00adgent\u00adlich. Das ist auf Dau\u00ader ganz sch\u00f6n anstren\u00adgend. Au\u00dfer\u00addem besteht wie bei allen kosten\u00adlo\u00adsen Web\u00addien\u00adsten die Gefahr, dass ich eines Tages ohne ihn aus\u00adkom\u00admen muss. Ich habe mir also selbst eine Alter\u00adna\u00adti\u00adve ent\u00adwickelt, die auf einem mei\u00adner Ser\u00adver l\u00e4uft und deren kor\u00adrek\u00adte Funk\u00adti\u00adons\u00adwei\u00adse ich im Zwei\u00adfels\u00adfall also selbst sicher\u00adstel\u00adlen kann.<\/p>\n<p><!--more--><b>Die Wahl der Pro\u00adgram\u00admier\u00adspra\u00adche<\/b><\/p>\n<p>Ein Bin\u00e4r\u00adpro\u00adgramm, zum Bei\u00adspiel in C++, w\u00e4re hier zu unfle\u00adxi\u00adbel, auf Ser\u00advern bevor\u00adzu\u00adge ich \u2013 schon aus Gr\u00fcn\u00adden der Wart\u00adbar\u00adkeit und damit Sicher\u00adheit \u2013 rei\u00adne Script\u00adspra\u00adchen. Wie \u00fcblich stand ich also vor der Ent\u00adschei\u00addung, ob ich mich f\u00fcr Perl, Python oder Com\u00admon Lisp (<em>absicht\u00adlich ver\u00adein\u00adfach\u00adte<\/em> Lisp-Dia\u00adlek\u00adte wie Sche\u00adme und Racket kann ich nicht ernst neh\u00admen) ent\u00adschei\u00adden soll\u00adte.<\/p>\n<p>Alle drei Spra\u00adchen bie\u00adten her\u00advor\u00adra\u00adgen\u00adde HTML- und XML-Biblio\u00adthe\u00adken, sie sind f\u00fcr ein schnel\u00adles <em>pro\u00adto\u00adty\u00adp\u00ading<\/em> auch glei\u00adcher\u00adma\u00ad\u00dfen effi\u00adzi\u00adent zu nut\u00adzen. An Python aller\u00addings st\u00f6\u00adren mich nach wie vor die feh\u00adlen\u00adden Klam\u00admern, die ein <em>refac\u00adto\u00adring<\/em> w\u00e4h\u00adrend des Ent\u00adwick\u00adlungs\u00adpro\u00adzes\u00adses nen\u00adnens\u00adwert auf\u00adhal\u00adten w\u00fcr\u00adden: Ein\u00adr\u00fcckung ist Syn\u00adtax, \u00c4nde\u00adrun\u00adgen im Pro\u00adgramm\u00adab\u00adlauf las\u00adsen sich also nicht ein\u00adfach mit ein paar Klam\u00admern vor\u00adneh\u00admen. Python mag <em>ein\u00adfach<\/em> sein, aber es nervt. \u2013 In einem ersten Ent\u00adwurf f\u00fcr die\u00adses Pro\u00adjekt hat\u00adte ich dank der guten <a href=\"https:\/\/docs.python.org\/3\/library\/sqlite3.html\"><tt>sqlite3<\/tt>-Biblio\u00adthek<\/a> recht schnell ein lauf\u00adf\u00e4\u00adhi\u00adges Python-Script, das zumin\u00addest mei\u00adne Daten\u00adbank ver\u00adwal\u00adten konn\u00adte (dazu unten mehr), fer\u00adtig\u00adge\u00adstellt, aber auch unge\u00adz\u00e4hl\u00adte graue Haa\u00adre mehr am K\u00f6r\u00adper; auch, weil Python <a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0020\/\">recht geschw\u00e4t\u00adzig<\/a> ist: \u201eExpli\u00adcit is bet\u00adter than impli\u00adcit\u201c, was pri\u00adma ist f\u00fcr Leu\u00adte, die nach Code\u00adzei\u00adlen bezahlt wer\u00adden, aber ungut f\u00fcr Leu\u00adte, die gern m\u00f6g\u00adlichst wenig Zeit ver\u00adschwen\u00adden w\u00fcr\u00adden. (Es wirkt iro\u00adnisch, dass ich das als Teil einer wort\u00adrei\u00adchen Erkl\u00e4\u00adrung f\u00fcr eigent\u00adlich Tri\u00advia\u00adles anmer\u00adke, nicht?)<\/p>\n<p>Das von mir anson\u00adsten sehr gesch\u00e4tz\u00adte Perl hat die\u00adses Pro\u00adblem nicht, aller\u00addings kommt es mir in einem ande\u00adren Punkt <em>in die Que\u00adre<\/em>: Die Ent\u00adwick\u00adler\u00adgrup\u00adpe hin\u00adter Mojo\u00adli\u00adcious, der <em>freund\u00adlich\u00adsten<\/em> Biblio\u00adthek zum Ver\u00adar\u00adbei\u00adten von Web\u00adsites, h\u00e4lt offen\u00adbar nicht beson\u00adders viel von sta\u00adbi\u00adlen APIs, erst Anfang M\u00e4rz muss\u00adte ein auf Mojo\u00adli\u00adcious basie\u00adren\u00addes Web\u00adpro\u00adjekt, das ich <em>aus Gr\u00fcn\u00adden<\/em> im Auge behal\u00adte, pl\u00f6tz\u00adlich <a href=\"https:\/\/github.com\/preaction\/Statocles\/commit\/0f2f548b99214cfdaf3295e0e588bdccca38b159\">nach\u00adbes\u00adsern<\/a>, was mich ver\u00adun\u00adsi\u00adchert hat: Ich m\u00f6ch\u00adte das Werk\u00adzeug, wenn es fer\u00adtig ist, wahr\u00adschein\u00adlich gern noch ein paar Jah\u00adre lang nut\u00adzen, ohne wegen eines System\u00adup\u00addates funk\u00adtio\u00adnie\u00adren\u00adde abstra\u00adhier\u00adte Rou\u00adti\u00adnen umschrei\u00adben zu m\u00fcs\u00adsen.<\/p>\n<p>\u00dcbrig bleibt also Com\u00admon Lisp. Das wird lustig.<\/p>\n<p><b>Die Wahl der Daten\u00adbank<\/b><\/p>\n<p>Da die Feeds <em>nat\u00fcr\u00adlich<\/em> nicht nur in Datei\u00adform vor\u00adlie\u00adgen, son\u00addern zun\u00e4chst ein\u00admal gene\u00adriert und gele\u00adgent\u00adlich aktua\u00adli\u00adsiert wer\u00adden sol\u00adlen, muss eine Liste der zu gene\u00adrie\u00adren\u00adden Feeds und (um Dupli\u00adka\u00adte zu ver\u00admei\u00adden) der bis\u00adhe\u00adri\u00adgen Ein\u00adtr\u00e4\u00adge zumin\u00addest ein\u00adfach edi\u00adtier\u00adbar vor\u00adlie\u00adgen. Eine <em>auf\u00adge\u00adbla\u00adse\u00adne<\/em> Daten\u00adbank wie MariaDB w\u00e4re zwar eine funk\u00adtio\u00adnie\u00adren\u00adde, aber nicht unbe\u00addingt die offen\u00adsicht\u00adlich beste L\u00f6sung. Ich habe mich f\u00fcr SQLi\u00adte ent\u00adschie\u00adden, das die gesam\u00adte Daten\u00adbank platz\u00adspa\u00adrend in einer ein\u00adzi\u00adgen Datei ablegt und mit <a href=\"https:\/\/github.com\/fukamachi\/datafly\">datafly<\/a> auch aus Com\u00admon Lisp her\u00adaus benutz\u00adbar ist.<\/p>\n<p>Dazu gen\u00fcgt mir fol\u00adgen\u00addes Daten\u00adbank\u00adsche\u00adma:<\/p>\n<pre lang=\"sql\">CREATE TABLE entries (\n  id integer primary key autoincrement,\n  feedid integer,\n  title text not null,\n  contents blob,\n  url text not null,\n  timestamp integer\n);\nCREATE TABLE feeds (\n  id integer primary key autoincrement,\n  feedtitle text not null,\n  url text not null,\n  entryselector text not null,\n  titleselector text not null,\n  contentselector text not null,\n  lastsuccess integer\n);<\/pre>\n<p>Den \u201eletz\u00adten Erfolg\u201c eines Feeds m\u00f6ch\u00adte ich zumin\u00addest spei\u00adchern, um sp\u00e4\u00adter leich\u00adter zu sehen, ob der Cron\u00adjob noch ord\u00adnungs\u00adge\u00adm\u00e4\u00df funk\u00adtio\u00adniert. Zur Funk\u00adti\u00adons\u00adwei\u00adse kom\u00adme ich aber wei\u00adter unten noch.<\/p>\n<p><b>Die Umge\u00adbung<\/b><\/p>\n<p>Da die von mir gew\u00e4hl\u00adten Kom\u00adpo\u00adnen\u00adten recht por\u00adta\u00adbel sind, ist die Wahl des Betriebs\u00adsy\u00adstems erst ein\u00admal nicht so wich\u00adtig. Vor\u00adhan\u00adden sein soll\u00adte neben SQLi\u00adte auch eine <a href=\"https:\/\/de.wikipedia.org\/wiki\/Vergleich_von_Common-Lisp-Implementierungen\">Ver\u00adsi\u00adon von Com\u00admon Lisp<\/a> mit instal\u00adlier\u00adtem <a href=\"https:\/\/www.quicklisp.org\/beta\/\">Quick\u00adlisp<\/a>. Ich habe mich f\u00fcr <a href=\"http:\/\/sbcl.org\/\">SBCL<\/a> ent\u00adschie\u00adden. Das Script soll\u00adte im Prin\u00adzip auch unter <a href=\"http:\/\/ccl.clozure.com\/\">Clo\u00adzu\u00adre CL<\/a>, das ich am hei\u00admi\u00adschen Lap\u00adtop f\u00fcr <a href=\"https:\/\/common-lisp.net\/project\/slime\/\">SLIME<\/a> nut\u00adze, lau\u00adfen, aber dort ist es momen\u00adtan nicht m\u00f6g\u00adlich, ein Script so kom\u00adfor\u00adta\u00adbel direkt aus der Kom\u00adman\u00addo\u00adzei\u00adle her\u00adaus auf\u00adzu\u00adru\u00adfen, wie <tt>sbcl \u2013script<\/tt> es mir erm\u00f6g\u00adlicht.<\/p>\n<p>Nun kann es los\u00adge\u00adhen.<\/p>\n<p><b>Das Script<\/b><\/p>\n<p>Um mir das Testen und Kor\u00adri\u00adgie\u00adren so ein\u00adfach wie m\u00f6g\u00adlich zu machen, habe ich den Code ent\u00adge\u00adgen \u00fcbli\u00adchen Gepflo\u00adgen\u00adhei\u00adten nicht in meh\u00adre\u00adre Datei\u00aden auf\u00adge\u00adteilt. Beim Laden des Scripts wer\u00adden per Quick\u00adlisp die n\u00f6ti\u00adgen exter\u00adnen Biblio\u00adthe\u00adken gela\u00adden und gege\u00adbe\u00adnen\u00adfalls instal\u00adliert, sofern noch nicht vor\u00adhan\u00adden; die\u00adse Instal\u00adla\u00adti\u00adon macht sich beim Auf\u00adruf in einer kur\u00adzen War\u00adte\u00adzeit bemerk\u00adbar, aber das ist noch ertr\u00e4g\u00adlich. Die ver\u00adschie\u00adde\u00adnen Betriebs\u00admo\u00addi haben jeweils einen eige\u00adnen Code\u00adbe\u00adreich, der aus der Haupt\u00adfunk\u00adti\u00adon her\u00adaus auf\u00adge\u00adru\u00adfen wird.<\/p>\n<p>Damit ihr den Code nicht umst\u00e4nd\u00adlich hier her\u00adaus\u00adko\u00adpie\u00adren m\u00fcsst und um den Text hier noch eini\u00adger\u00adma\u00ad\u00dfen \u00fcber\u00adsicht\u00adlich zu hal\u00adten, habe ich ein <a href=\"https:\/\/code.rosaelefanten.org\/rssparser.lisp\">Pro\u00adjekt<\/a> <em>(Nach\u00adtrag vom 8. August 2024: Link repa\u00adriert)<\/em> ange\u00adlegt, wo k\u00fcnf\u00adtig die aktu\u00adell\u00adste Ver\u00adsi\u00adon des Codes zu fin\u00adden ist.<\/p>\n<p>Die Bedie\u00adnung des RSS-Par\u00adsers ist eigent\u00adlich selbst\u00ader\u00adkl\u00e4\u00adrend:<\/p>\n<pre>% .\/rssparser.lisp\nSyntax:\n* rssparser.lisp add &lt;Title&gt; &lt;URL&gt; &lt;EntrySelector&gt; &lt;TitleSelector&gt; [&lt;ContentSelector&gt;]\n* rssparser.lisp delete &lt;ID&gt;\n* rssparser.lisp list\n\nIf you're a bot:\n* rssparser.lisp parse<\/pre>\n<p>Das nach\u00adtr\u00e4g\u00adli\u00adche \u00c4ndern von Feeds ist nicht vor\u00adge\u00adse\u00adhen, um die Inte\u00adgri\u00adt\u00e4t der bereits erstell\u00adten Feed\u00adda\u00adtei\u00aden nicht zu gef\u00e4hr\u00adden.<\/p>\n<p><b>Funk\u00adti\u00adons\u00adwei\u00adse<\/b><\/p>\n<p>Da jeder Feed auf Grund\u00adla\u00adge von CSS-Selek\u00adto\u00adren erstellt wird, m\u00fcs\u00adsen die\u00adse zun\u00e4chst ermit\u00adtelt wer\u00adden. Das geht mit den Ent\u00adwick\u00adler\u00adwerk\u00adzeu\u00adgen, die in den mei\u00adsten aktu\u00adel\u00adlen Brow\u00adsern zur Ver\u00adf\u00fc\u00adgung ste\u00adhen, ziem\u00adlich ein\u00adfach. Ich mache mal \u2019n Bei\u00adspiel: Neh\u00admen wir an, ich w\u00fcr\u00adde gern den jeweils aktu\u00adel\u00adlen Ent\u00adwick\u00adlungs\u00adstand von <a href=\"http:\/\/www.9bis.net\/kitty\/?action=news&amp;zone=en\">KiT\u00adTY<\/a> abon\u00adnie\u00adren. Im Web\u00adbrow\u00adser mei\u00adner Wahl besu\u00adche ich also die Sei\u00adte mit den aktu\u00adel\u00adlen \u00c4nde\u00adrun\u00adgen und dr\u00fccke auf <tt>F12<\/tt>.<\/p>\n<p>Ich ben\u00f6\u00adti\u00adge hier jeweils den CSS-Selek\u00adtor f\u00fcr einen Nach\u00adrich\u00adten\u00adein\u00adtrag, sei\u00adnen Titel und sei\u00adnen Inhalt. Nach\u00adrich\u00adten\u00adein\u00adtr\u00e4\u00adge sind auf der KiT\u00adTY-Web\u00adsite, wie der Brow\u00adser mir zeigt, in <tt>DIV<\/tt>-Ele\u00admen\u00adten mit der Klas\u00adse <tt>news<\/tt> grup\u00adpiert und ihre \u00dcber\u00adschrif\u00adten in <tt>H1<\/tt>-Tags. Geson\u00adder\u00adte Berei\u00adche f\u00fcr die Inhal\u00adte gibt es nicht, ich kann den letz\u00adten Para\u00adme\u00adter nun also ent\u00adwe\u00adder weg\u00adlas\u00adsen (dann wer\u00adden nur die \u00dcber\u00adschrif\u00adten im Feed gespei\u00adchert) oder einen lee\u00adren String \u00fcber\u00adge\u00adben (dann wird der gan\u00adze Nach\u00adrich\u00adten\u00adein\u00adtrag als Inhalt gespei\u00adchert). Ich ent\u00adschei\u00adde mich f\u00fcr Letz\u00adte\u00adres, denn die Liste der \u00c4nde\u00adrun\u00adgen m\u00f6ch\u00adte ich gern kom\u00adplett \u2013 also nicht nur die Ver\u00adsi\u00adons\u00adnum\u00admern \u2013 abon\u00adnie\u00adren.<\/p>\n<pre>% .\/rssparser.lisp add \"KiTTY\" \"http:\/\/www.9bis.net\/kitty\/?action=news&amp;zone=en\" \".news\" \"h1\" \"\"\nSuccess!<\/pre>\n<p>Wird <tt>rssparser.lisp par\u00adse<\/tt> aus\u00adge\u00adf\u00fchrt oder gleich als Cron\u00adjob instal\u00adliert, so wer\u00adden regel\u00adm\u00e4\u00ad\u00dfig alle Feeds als RSS-XML-Datei\u00aden im Ord\u00adner <tt>feeds\/<\/tt> abge\u00adlegt bezie\u00adhungs\u00adwei\u00adse aktua\u00adli\u00adsiert; even\u00adtu\u00adell nicht mehr erreich\u00adba\u00adre Web\u00adsites wer\u00adden nach einer Sta\u00adtus\u00admel\u00addung auto\u00adma\u00adtisch aus der Liste gel\u00f6scht. Die erzeug\u00adten Feeds las\u00adsen sich dann im RSS-Leser eurer Wahl abon\u00adnie\u00adren. Ein Auf\u00adruf des Feeds im Fire\u00adfox zeigt: Es hat geklappt.<\/p>\n<p><a href=\"https:\/\/tuxproject.de\/blog\/wp-content\/uploads\/2016\/03\/rssparser-Screenshot.png\" rel=\"attachment wp-att-11250\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-11250\" src=\"https:\/\/tuxproject.de\/blog\/wp-content\/uploads\/2016\/03\/rssparser-Screenshot-300x257.png\" alt=\"rssparser Screenshot\" width=\"300\" height=\"257\" srcset=\"https:\/\/tuxproject.de\/blog\/wp-content\/uploads\/2016\/03\/rssparser-Screenshot-300x257.png 300w, https:\/\/tuxproject.de\/blog\/wp-content\/uploads\/2016\/03\/rssparser-Screenshot-120x103.png 120w, https:\/\/tuxproject.de\/blog\/wp-content\/uploads\/2016\/03\/rssparser-Screenshot-768x658.png 768w, https:\/\/tuxproject.de\/blog\/wp-content\/uploads\/2016\/03\/rssparser-Screenshot.png 897w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\"><\/a><\/p>\n<p>Ihr k\u00f6nnt den Ord\u00adner f\u00fcr die XML-Datei\u00aden \u00fcber die Kon\u00adstan\u00adte <tt>+feed-fol\u00adder+<\/tt> auch \u00e4ndern, beach\u00adtet aber, dass Schreib\u00adrech\u00adte f\u00fcr den Ziel\u00adord\u00adner vor\u00adhan\u00adden sein m\u00fcs\u00adsen.<\/p>\n<p><b>Gibt es kein GUI?<\/b><\/p>\n<p>Gra\u00adfi\u00adsche Ober\u00adfl\u00e4\u00adchen sind bei Pro\u00adgram\u00admen, die auf Web\u00adser\u00advern lau\u00adfen und nicht st\u00e4n\u00addig bemut\u00adtert wer\u00adden m\u00fcs\u00adsen, im Prin\u00adzip nur unn\u00fct\u00adzer \u00dcber\u00adhang, ein Web\u00adin\u00adter\u00adface f\u00fcr <a href=\"https:\/\/www.dietmarjanowski.de\/wordpress\/\">Leu\u00adte<\/a>, die Angst vor der Kon\u00adso\u00adle haben, w\u00e4re mit\u00adtels <a href=\"http:\/\/8arrow.org\/caveman\/\">Caveman2<\/a> oder <a href=\"http:\/\/eudoxia.me\/lucerne\/\">Lucer\u00adne<\/a> aber ohne all\u00adzu gro\u00ad\u00dfen Auf\u00adwand nach\u00adr\u00fcst\u00adbar. Die SQLi\u00adte-Daten\u00adbank l\u00e4sst sich aller\u00addings auch mit Werk\u00adzeu\u00adgen wie dem <a href=\"http:\/\/sqlitebrowser.org\/\">SQLi\u00adte Data\u00adba\u00adse Brow\u00adser<\/a> pfle\u00adgen.<\/p>\n<p><b>Fazit<\/b><\/p>\n<p>Das war jetzt ein biss\u00adchen mehr Arbeit als ange\u00adnom\u00admen, aber das Ergeb\u00adnis ist ein auf mei\u00adnen Zweck zuge\u00adschnit\u00adte\u00adnes Pro\u00adgramm, das ohne \u00fcber\u00adfl\u00fcs\u00adsi\u00adge \u201eExtras\u201c und vor allem ohne Wer\u00adbung aus\u00adkommt und das nicht zu funk\u00adtio\u00adnie\u00adren auf\u00adh\u00f6rt, so lan\u00adge ich es brau\u00adche. Theo\u00adre\u00adtisch lie\u00ad\u00dfe sich das Script auch in eine por\u00adta\u00adble Bin\u00e4r\u00adda\u00adtei kom\u00adpi\u00adlie\u00adren, das w\u00fcr\u00adde die Wart\u00adbar\u00adkeit aber wie\u00adder\u00adum ver\u00adrin\u00adgern.<\/p>\n<p>Erg\u00e4n\u00adzun\u00adgen, Lob\u00adprei\u00adsun\u00adgen und Gewinn\u00adbe\u00adtei\u00adli\u00adgun\u00adgen sind will\u00adkom\u00admen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Novem\u00adber 2015 schrieb ich, der kosten\u00adlo\u00adse Web\u00addienst feed43 sei zum Ent\u00adm\u00fcl\u00adlen von Web\u00adsites mit\u00adtels RSS prin\u00adzi\u00adpi\u00adell geeig\u00adnet, ver\u00adschlucke sich aber gele\u00adgent\u00adlich. Das ist auf Dau\u00ader ganz sch\u00f6n anstren\u00adgend. Au\u00dfer\u00addem besteht wie bei allen kosten\u00adlo\u00adsen Web\u00addien\u00adsten die Gefahr, dass ich eines Tages ohne ihn aus\u00adkom\u00admen muss. Ich habe mir also selbst eine Alter\u00adna\u00adti\u00adve ent\u00adwickelt, die \u2026<\/p>\n<p><a href=\"https:\/\/tuxproject.de\/blog\/2016\/03\/mit-common-lisp-gegen-webmuell\/\" class=\"more-link\">\u2018Mit Com\u00admon Lisp gegen Web\u00adm\u00fcll\u2019 wei\u00adter\u00adle\u00adsen \u00bb<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wp_typography_post_enhancements_disabled":false,"footnotes":""},"categories":[5,19],"tags":[],"series":[],"class_list":["post-11249","post","type-post","status-publish","format-standard","hentry","category-projekte","category-nerdkrams"],"share_on_mastodon":{"url":"","error":""},"wp-worthy-pixel":{"ignored":false,"public":"e5ca517f311e4fbfa00f55edf6263b39","server":"vg02.met.vgwort.de","url":"https:\/\/vg02.met.vgwort.de\/na\/e5ca517f311e4fbfa00f55edf6263b39"},"wp-worthy-type":"normal","_links":{"self":[{"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/posts\/11249","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/comments?post=11249"}],"version-history":[{"count":0,"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/posts\/11249\/revisions"}],"wp:attachment":[{"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/media?parent=11249"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/categories?post=11249"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/tags?post=11249"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/tuxproject.de\/blog\/wp-json\/wp\/v2\/series?post=11249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}