SEO-Monitoring mit Crawlabgleichen in R – 2020 Version

Bekanntlich ist es sinnvoll eine Website während der Umsetzung des SEO-Konzepts sowie im Rahmen der Betreuung genaustens im Auge zu behalten. Eine der mächtigsten Instrumente um immer auf dem neusten Stand zu sein, ist das zeitversetzte Crawlen und Abgleichen der Website basierend auf der URL Basis. Um den regelmäßigen Zeitaufwand dafür auf ein Minimum zu reduzieren, werden wir in diesem Beitrag alles vom Crawling bis zum Output-Excel automatisieren! Anders ausgedrückt, das Einzige was zu tun ist neben der initialen Einrichtung, ist die intellektuelle Analyse des Ausgabe-Excel.

Da unser letzter Blog-Beitrag zu diesem Thema schon einige Zeit her ist und wir uns bei [Get:Traction] natürlich auch ständig weiterentwickeln, ist es an der Zeit, mal wieder ein Update zu lancieren! Optimierung ist schließlich der Inbegriff unserer Kernkompetenz.

Der Output – Was kommt dabei raus?

Um abzuklären, ob der Crawlabgleich etwas für Dich ist, ist es sinnvoll zuerst einmal einen Blick auf den Output zu werfen:

Das Endergebnis ist nach wie vor eine Excel Datei, welche in einem Reiter für jede Metrik die Unterschiede zum vorherigen Crawl aufzeichnet. Dabei sind folgende Punkte abgedeckt:

  • Neue URLs
  • Nicht mehr verlinkte URLs
  • Änderungen bei URLs, die in beiden Crawls vorhanden sind:
    • Status Codes
    • Canonical-Anweisungen
    • Meta Robots
    • H1
    • Titles
    • Descriptions
    • Content Types
    • Klicktiefe
    • Dateigröße
R Crawlabgleich Excel

Übersicht der Arbeitsschritte

Grundsätzlich haben wir 3 Schritte während des gesamten Prozesses:

– Wir crawlen die Website in Zeitabständen

– Wir vergleichen die Crawls miteinander

– Wir analysieren das Endergebnis

Seo-Monitoring Arbeitsschritte

Crawlen der Website

Für diesen Arbeitsschritt benötigen wir die Screaming-Frog SEO Spider.

Erstellen der Ordnerstruktur und Einrichtung der Crawl-Jobs im Aufgabenplaner

Um unseren Export nach beliebigen Zeitabständen zu automatisieren und damit regelmäßig viel Zeit zu sparen, legen wir eine standardisierte Ordnerstruktur an und erstellen im Windows Aufgabenplaner Jobs für das Crawling.

Ordnerstruktur

Initial benötigen wir 4 Ordner, die alle im gleichen Verzeichnis abzulegen sind:

R Crawlabgleiche Ordnerstruktur

Die Struktur sieht folgendermaßen aus:

  • 01_crawl_abgleiche
    • /[Kunde]
      • Hier kommen die vom R-Skript generierten XLSX rein.
  • 02_sf_exports
    • /[Kunde]
      • /[yyyy.mm.dd.hh.mm.ss]
        • Hier legt der Screaming Frog automatisch seine Exporte ab. Zum einen den „internal_all.csv“. Zum anderen – um im Nachhinein im Detail nachsehen zu können – den gesamten Crawl als „.seospider“.
  • 03_sf_configs
    • Hier liegen die Screaming-Frog Konfigurationsdateien ab (sofern vorhanden).
  • 04_R
    • /[R-Projekt]
      • Hier liegt das „.R“-Projekt, welches aus den letzten beiden Crawls für eine Website den Abgleich bastelt und diesen in „01_crawlabgleiche/[Kunde]/“ abglegt.

Alle fett geschriebenen Ordner in der obigen Darstellung müssen einmal initial angelegt werden. Der Rest wird automatisch von unserem Skript und dem SF generiert.

Windows Job für Crawls

  1. Erstellen der 4 initialen Ordner.
  2. Erstellen eines Ordners für jeden Kunden unter 02_sf_exports.
  3. Wenn Screaming-Frog Konfigurationsdateien für die vorgesehenen Crawls vorhanden sind, diese im Ordner „03_sf_configs“ ablegen.
  4. Öffne die „Aufgabenplanung“ über die Windows-Suche.
  5. Es ist empfehlenswert einen neuen Ordner für die Crawlings sowie die R-Jobs in der Aufgabenplanung zu erstellen:
R Crawlabgleiche Aufgabenplanung
  1. Navigiere in den neu erstellten Ordner
  2. Erstelle mit Rechtsklick -> „Neue Aufgabe erstellen“ eine neue Aufgabe
  3. Im Dialogfeld müsst ihr dem Job nun einen Namen geben (Hier empfiehlt es sich die Namensgebung zu standardisieren und das Intervall mit einzubeziehen z.B. „1month_kunde“. Unter dem Reiter „Trigger“ könnt ihr das gewünschte Intervall und die Ausführungstage festlegen. Wir crawlen bspw. wöchentlich. Das sähe dann so aus:
R Crawlabgleiche Aufgabenplanung Trigger
  1. Im Reiter Aktion legen wir nun den Job folgendermaßen an:
  • Kopiert euch den Pfad der „ScreamingFrog CLI“ mittels „Shift-Rechtsklick“ -> „Als Pfad kopieren“
  • („C:\Program Files (x86)\Screaming Frog SEO Spider\ScreamingFrogSEOSpiderCli.exe“)
  • Klickt auf „Neu“ und tragt den Kopierten Pfad im Feld „Programm/Skript“ ein
  • Kopiert nun in das Feld „Argumente hinzufügen“ folgenden Text:

–project-name Kunden_Crawlabgleiche –task-name 1month_tue_1200_kunde –crawl „https://www.beispiel.de/“ –config „C:\03_sf_configs\kunde.seospiderconfig“ –headless –output-folder „C:\02_sf_exports\kunde“ –timestamped-output –save-crawl –export-tabs Internal%3AAll –export-format csv

  • Ersetzt nun alle fett markierten Stellen im Text durch eure eigenen Angaben.
    • Kunden_Crawlabgleiche ist der Projektname im Screaming-Frog. Kann dort angelegt werden. (Optionaler Parameter)
    • 1_month_tue_1200_[kunde] ist der Name des Tasks im Screaming-Frog.
    • Die URL ist die zu crawlende website
    • Die beiden Pfade geben einmal den Ort der zu nutzenden SF-Config für den Crawl an und den Output Folder. Hier muss der Pfad in den jeweiligen Kunden Ordner unter /02_sf_exports rein.
  • Eine Dokumentation zu den genutzten Parametern findet sich hier.

Das Endergebnis sieht dann so aus:

R Crawlabgleiche Aufgabenplaner Aktion

Jetzt könnt Ihr auf OK klicken und den Job speichern. Damit haben wir unseren automatisierten Crawl!

Abgleichen der Websites

Für diesen Arbeitsschritt benötigen wir R Studio. Hier eine kurze Anleitung und Erklärung zur Installation.

Anlegen des R-Skripts und Erstellen von Windows-Jobs

Anlegen des R-Skripts

  • Ladet euch den Ordner hier von unserem Git-Hub herunter.
  • Hier befinden sich 2 Dateien („website_change_monitor.R“ und „FUNS.R“)
  • Öffnet R Studio und legt ein neues R-Project im Ordner /04_R/ an.
  • Kopiert jetzt die beiden Dateien aus dem Download in euren Projektordner („/04_R/[Projektname]/“)

Jetzt müssen wir nur noch 2 Pfade im R Skript anpassen und schon haben wir alles für unseren Windows Job vorbereitet!

Navigiert hierzu in R Studio in eurem Projekt in die Datei „website_change_monitor.R“ und passt folgende Variablen an:

R Crawlabgleiche Skript Pfade

PATH_TO_XLSX_EXPORTS ist der Pfad in euren /01_crawl_abgleiche Ordner.

PATH_TO_SF_EXPORTS ist der Pfad in euren /02_sf_exports Ordner.

(Tipp: Um auf der sicheren Seite zu sein könnt ihr „C:/“ eingeben und dann mit TAB und den Pfeiltasten bis in den jeweiligen Ordner navigieren)

Speichert das Skript jetzt mit „STRG & S“.

Damit das Skript funktioniert müsst ihr ein paar R Packages installieren. Das geht ganz einfach indem ihr am oberen Rand in R Studio auf den hints „install“ durchklickt. Sollten die Meldungen nicht aufpoppen, könnt ihr alle Packages folgendermaßen installieren:

Als Beispiel einmal:

Die Namen aller benötigten Packages findet ihr unter #1 Libraries (alle die mit „library()“ geladen werden) im Skript.

Anlegen des Windows-Jobs für das R-Skript

  1. Legt euch wieder im Aufgabenplaner einen neuen Ordner für R an.
  2. Erstellt hier eine neue Aufgabe mit Namen und Trigger. Der Trigger sollte natürlich nach dem ausführen der Crawl Jobs gesetzt werden.
  3. Gebt im Feld „Programm/Skript“ den Pfad zu eurer R-Installation ein, ungefähr so: „C:\Program Files\R\R-3.6.1\bin\Rscript.exe“
  4. Im Feld „Argumente hinzufügen“ geben wir nun den Dateinamen des R-Skripts an: „website_change_monitor.R“
  5. Im Feld „Starten in“ geben wir den Pfad des Ordners an, in dem sich das Skript befindet: „/04_R/[Projektname]/“
  6. Jetzt können wir den Job speichern!
R Crawlabgleiche Aufgabenplanung Skript Aktion

Das wars! Jetzt haben wir einen völlig automatisierten Crawlabgleich. Zur Einrichtung eines weiteren Abgleichs, müsst ihr nur einen Ordner für den neuen Kunden in 02_sf_exports erstellen und einen Crawl-Job im Windows Aufgabenplaner erstellen. Das Skript registriert den neuen Kunden von alleine. Eure Output-Excels findet ihr nun im Ordner /01_Crawl_Abgleiche/.

Das Skript in allen Einzelheiten

Libraries

Hier werden die zum Ausführen des Skripts benötigten R-Packages geladen. Um diese beim Ausführen des Skripts nutzen zu können, müsst ihr diese vorher installieren (Beschrieben in Punkt Anlegen des R-Skripts).

Vars

Hier werden die Pfade für die Imports und Exports festgelegt. Zusätzlich legen wir hier unseren Slack API Key als Variable (Auskommentiert da nicht essenziell) an, um erfolgreich ausgeführte Scripts sowie Fehlermeldungen in unseren Scripts- Slack Channel automatisiert zu pushen! Damit hat man also auch ein Warnsystem implementiert. Die Variable „#TESTING_WEBSITE“ ist standardmäßig auskommentiert mit einem #. Sollte man Adhoc nur eine einzige Website vergleichen wollen, kann man hier das # entfernen und in die Gänsefüßchen die Website schreiben. Dabei einfach den Namen des Ordners verwenden, wie ihr ihn im sf_exports Verzeichnis erstellt habt.

Slack

Hier wird dem „slackR“ Package die nötige Information mitgegeben. Den API Key, in welchen Channel soll gepusht werden? Unter welchem Namen sollen die Nachrichten dort auftauchen?

Die Sektion ist im download-Skript ebenfalls auskommentiert, da die Nutzung von SlackR natürlich nicht obligatorisch ist.

Get Files

Find all CSV’s

Hier werden alle Dateien mit .csv-Endung rekursiv aus dem in der Variable PATH_TO_SF_EXPORTS enthaltenen Pfad aufgelistet.

Split paths

Nun splitten wir die Pfade der aufgelisteten Dateien in dem Dataframe „df_file_paths“ in einzelne Spalten auf.

Extract website, datetime

Hier determinieren wir, welche Teile der in „df_file_paths“ enthaltenen Pfade welches Element sind und geben den entsprechenden Spalten die Namen.

Convert to date

Hier konvertieren wir das bisher als Character zu verstehende Datum in der Spalte „datetime“ in ein richtiges Datums-Datenformat. Dazu nutze ich die äußerst nutzvolle Library Lubridate.

Check if two Crawls exist

Wir gruppieren nach der Spalte „website“ und zählen, ob die Anzahl an Elementen pro Gruppe mehr als 1 beträgt. Anschließend lösen wir die Gruppierung wieder auf.

Get last two crawls

Wir gruppieren abermals nach „website“ und fügen dem Dataframe die Spalte „date_rank“ hinzu. Dieser wird mithilfe der rank() Funktion absteigend durch die Spalte „datetime“ berechnet. Abschliessend filtern wir auf Einträge mit „date_rank“ 1 & 2 und lösen die Gruppierung wieder auf.

Get Website for iteration

Um für jede Website einen einzelnen Crawl Abgleich bauen zu können, müssen wir jede Website als einzelnes Objekt einer Liste betrachten und die gleichen Aktionen für jedes Objekt in dieser Liste iterativ durchführen. Hierzu bedienen wir uns eines einfachen for()-loops. Diese Liste bereiten wir nun mithilfe der unique-Funktion vor. Diese gibt uns, nach Einspeisung der Spalte „websites“ aus „df_file_paths“, einen Vector ohne doppelte Werte zurück. Sprich – wir haben eine Liste aller unserer Websites, die als Iterationsobjekt benutzt werden können.

Filter for testing

Bevor wir mit dem eigentlichen Abgleich loslegen, gucken wir hier nach, ob die vorher angesprochene Variable „TESTING_WEBSITE“ besteht und wenn ja, filtern nur auf die dort enthaltene Website.

Compare Crawls

Wir iterieren über unseren „websites“ vector und führen für jede enthaltene Website folgende Aktionen aus:

Am Anfang des Loops reduzieren wir das in dieser Iteration behandelte Datenset auf die Daten einer einzigen Website und setzen temporäre Variablen für das neue und alte Crawldatum. Wir geben eine Message in der Console aus und lesen beide Crawls, mithilfe der in „FUNS.R“ definierten Funktion „read_crawl“, ein. Dazu fügen wir eine Spalte mit neuem/altem Datum an.

Create website-dir if not exists

Der Kommentar ist ziemlich treffend – wir kreieren (wenn nicht vorhanden) ein Verzeichnis mithilfe des Iterationsobjektes sowie des Pfads aus PATH_TO_XLSX_EXPORTS.

Get new (linked) URLs

Abermals eine Message in die Console. Hier filtern wir innerhalb eines Anti-Joins vom neuen auf den alten Crawl, auf URLs, in dessen „content“ Spalte „html“ vorkommt oder die „status“ Spalte dem String „Connection Timeout“ entspricht.

Dabei bleiben nur noch die im neuen Crawl enthaltenen URLs zurück, die im alten nicht mehr existieren. Wir wählen per „select“ aus, welche Spalten wir haben wollen und konvertieren das ganze in ein Dataframe, da die XLSX Library kein Tibble versteht.

Get no longer linked/ deleted URLs

Message in die Console. Gleiches Vorgehen wie bei Punkt 4.5.2 Nur hier Anti-joinen wir vom alten auf den Neuen Crawl.

Get Status Code of not linked/deleted URLs

Message. Hier prüfen wir den Status Code der nicht mehr verlinkten Seiten, da wir ihn ja über den Crawl nicht kennen. Der Grund ist, dass wir prüfen wollen, ob eine Seite korrekterweise nicht mehr verlinkt ist. Antwortet die URL mit „404 Not Found“, ergibt es vollkommen Sinn, sie nicht mehr zu verlinken. Antwortet die Seite hingegen mit „200 OK“, stellt sich die Frage, warum sie nicht mehr verlinkt ist, wenn sie doch erreichbar ist. Im Hintergrund rennt hier ein parallelisierter Status-Code-Fetcher los. Je nachdem, wie viele URLs nicht mehr verlinkt sind, kann die Abfrage durchaus länger dauern. Auf der Console seht ihr aber die gerade abgefragten URLs, sodass ihr zumindest einen groben Überblick habt, dass sich noch etwas tut und dass das Skript nicht hängen geblieben ist. (Anhand dieses Punktes ist unter anderem erkennbar, dass es sinnvoll ist, die Crawls jeweils mit gleicher Konfiguration durchzuführen).

Get identical URLs

Was wohl 😉. Wir filtern auf HTML URLs beider Crawls und machen uns eines inner-Joins habhaft, um die identischen URLs des Abgleichs zu erhalten. Dazu fügen wir im Datenset Spalten für jedes Detail einer URL an, welche angeben, ob sich der entsprechende Wert geändert hat.

Get identical URL with changes

Da wir nun das Datenset an URLs definiert haben, welches in beiden Crawls enthalten ist, können wir nun die einzelnen Bestandteile dieses Datensets betrachten und vergleichen.

Verwaiste Seiten:

Hier definieren wir, je nach dem, was in unserer Spalte change_orphan_pages, die wir in Punkt 4.5.5 gebildet haben, steht, ob es sich um eine nicht mehr oder neu verwaiste Seite handelt. Dies speichern wir als Dataframe, um es später in der Excel abbilden zu können.

Dieses Vorgehen bleibt für jede Metrik das gleiche. Darum werde ich hier nicht auf jeden Unterpunkt eingehen.

Get biggest resources

Hier sortieren wir bei Images, JavaScript und CSS, absteigend nach der Größe (size_bytes) und speichern diese als DataFrame.

Create Excel

Hier nutzen wir die Library XLSX, um eine Arbeitsmappe zu erstellen und diese mit unseren sheets in der „sheet_order“ variable und den im Loop erstellten Data-Frames zu befüllen. Mit saveWorkbook() wird dem Export der Pfad übergeben und der Crawlabgleich, mit neuem und altem Datum im Namen, im entsprechenden Ordner der Website abgespeichert.

Send Slack notification (Fail, Success)

Zu guter Letzt unsere Slack-Notification. Hier wird eine Message aus dem momentanen Iterationsobjekt und einer vorgefertigten Nachricht zusammengebaut und mithilfe der vorher erstellten Variablen und des Packages SlackR in den Channel gepostet. Alle Slack-Inhalte sind im download-Skript auskommentiert, da die Nutzung von „SlackR“ rein optional ist.

Damit ist der For-Loop abgeschlossen und das Skript erstellt die Crawlabgleiche aller vorhandenen Websites.

Viel Spaß beim Abgleichen! Wenn ihr Fragen oder Anregungen habt, gerne kommentieren oder mir direkt eine Mail schreiben 🙂

Artikel teilen

The following two tabs change content below.
blank

David Meyer

Während meiner Ausbildung zum Applikationsentwickler in der Schweiz habe ich nach dem intensiven Einstieg in die Entwicklung das Thema Online Marketing entdeckt. Nach einem einjährigen Praktikum im Bereich Digital-Analytics bei einem schweizer Konzern hat mich letztlich die Suchmaschinenoptimierung in den Bann gezogen. Darum habe ich mich entschieden, in meine Heimatstadt Berlin zurückzukehren und bei [Get:Traction] tiefer in die Materie einzusteigen. Als Trainee im Bereich SEO-Analyse spezialisiere ich mich nun auf die nachhaltige On-Page Optimierung von Websites.
blank

Neueste Artikel von David Meyer (alle ansehen)

24 Comments on “SEO-Monitoring mit Crawlabgleichen in R – 2020 Version”

  1. Hi,

    I’m running in an error called:
    NA does not exist in the current working directory.

    I assume, that the path contains a mistake? Is that right?

    1. blank

      Hi Mike,

      that’s right. You have a backslash in your second path (C:\Users/). If you change it, it should work.

      Best regards,
      Patrick

  2. Thanks for your answer. Sorry that was a short mistake from my site. The error also exists with the right backslash.

    1. blank

      Hi Mike,

      that may be a stupid question, but are there two crawls in the folder? I.e., in your first comment you specified the path_to_crawls with "C:/Users/customerweb/Documents/Websiteaenderungen/Crawls/KUNDE_2017-12-01_internal_all". I did not notice the first time, but it seems to me that you are providing a file name instead of a folder.

      Suppose the two crawls KUNDE_2017-12-01_internal_all.csv and KUNDE_2017-12-08_internal_all.csv you would like to compare are located in your folder "C:/Users/customerweb/Documents/Websiteaenderungen/Crawls/ you have to assign the path_to_crawls-variable as follows: path_to_crawls <- "C:/Users/customerweb/Documents/Websiteaenderungen/Crawls/.

      If that is not the case let me know.

  3. Sehr cooles Skript. Bei einem Vergleich von 2 relativ großen Crawls (200.000 URLs) crashed mir allerdings R irgendwie immer mit einem "garbage collection overheat". Hast du dafür zufällig irgendeinen Tipp?

    1. blank

      Servus Dave,
      cool, dass dir das Skript gefällt. Blöd, dass R stirbt. Der Fehler ist mir noch nicht untergekommen. Ich würde jetzt aber ad hoc darauf tippen, dass dein RAM vollläuft und die garbage collection nicht hinterherkommt, neuen Speicherplatz frei zu machen. Das ist jetzt aber wirklich nur eine Vermutung.

      Wie viel RAM steht R denn zur Verfügung (in der Console memory.limit() ausführen)? Tritt der Fehler denn auch auf, wenn du kleinere Crawls miteinander vergleichst?

      Sollte es wirklich daran liegen, dass dein RAM vollläuft hift eigentlich nur mehr RAM. Oder das Skript müsste so umgeschrieben werden, dass die Crawls in einer Datenbank liegen und nicht im RAM zum Abgleich vorgehalten werden.

      Tut mir Leid, dass ich dir da nicht wirklich weiter helfen kann.

      LG

      1. Bei Crawls unter 10.000 URLs läuft alles super. Das Einlesen größerer Crawls ist übrigens auch kein Problem, es hängt am Ende dabei jedoch immer beim xlsx Schreiben (in der Global Environment sind die eingelesenen Variablen auch betrachtbar).

        Memory war bisher anscheinend laut memory.limit() auf 16000 mb begrenzt, hab das jetzt mal mit dem Befehl auf 50000 erhöht.
        Es müsste ja eigentlich entweder am generellen Ram, Java (ist eigentlich in der 64 bit Version installiert) oder dem Excel written/xlsx Befehl was gemacht werden können. Werde diese Woche dafür ein bisschen rumspielen mit der ganzen Sache.

        Nochmal danke für das Skript und deine Antwort 🙂

  4. Pingback: OMT 2018 Recap: Das lief bei der Online Marketing Konferenz

  5. Vielen Dank für das tolle Skript – wenn ich es nur zum Laufen bringen könnte 🙁

    Direkt am Anfang erhalte ich Meldungen zu irgendwelchen Konflikten. Ich kann damit leider gar nichts anfangen ….

    > library(tidyverse)
    ── Attaching packages ─────────────────────────────────────────────── tidyverse 1.2.1 ──
    ✔ ggplot2 3.2.1 ✔ purrr 0.3.3
    ✔ tibble 2.1.3 ✔ dplyr 0.8.3
    ✔ tidyr 1.0.0 ✔ stringr 1.4.0
    ✔ readr 1.3.1 ✔ forcats 0.4.0
    ── Conflicts ────────────────────────────────────────────────── tidyverse_conflicts() ──
    ✖ dplyr::filter() masks stats::filter()
    ✖ dplyr::lag() masks stats::lag()
    > library(lubridate)

    Attaching package: ‘lubridate’

    The following object is masked from ‘package:base’:

    date

    > library(stringr)
    > library(xlsx)
    Unable to find any JVMs matching version "(null)".
    No Java runtime present, try –request to install.
    Error: package or namespace load failed for ‘xlsx’:
    .onLoad failed in loadNamespace() for 'rJava', details:
    call: dyn.load(file, DLLpath = DLLpath, …)
    error: unable to load shared object '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/rJava/libs/rJava.so':
    dlopen(/Library/Frameworks/R.framework/Versions/3.6/Resources/library/rJava/libs/rJava.so, 6): Library not loaded: /Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/lib/server/libjvm.dylib
    Referenced from: /Library/Frameworks/R.framework/Versions/3.6/Resources/library/rJava/libs/rJava.so
    Reason: image not found
    In addition: Warning message:
    In system("/usr/libexec/java_home", intern = TRUE) :
    running command '/usr/libexec/java_home' had status 1
    > library(httr)

    Mittendrin dann weiteres Meldungen in rot:
    See spec(…) for full column specifications.
    Warning messages:
    1: Missing column names filled in: 'X3' [3], 'X8' [8], 'X11' [11], 'X14' [14], 'X16' [16], 'X18' [18], 'X20' [20], 'X22' [22], 'X24' [24], 'X25' [25], 'X26' [26], 'X27' [27], 'X28' [28], 'X29' [29], 'X30' [30], 'X31' [31], 'X35' [35], 'X43' [43], 'X44' [44], 'X45' [45], 'X46' [46], 'X47' [47]

    Error in stri_detect_regex(string, pattern, negate = negate, opts_regex = opts(pattern)) :
    argument str should be a character vector (or an object coercible to)

    Naja und dann am Ende noch

    Error in eval(lhs, parent, parent) : object 'internal_all_html' not found

    Habe R und R Studio frisch installiert. Kannst du mir Tipps geben, was da eventuell schief läuft?

    Danke!

    1. blank

      Hallo Stefan,
      vielen Dank für deinen Kommentar!
      Meine erste Einschätzung wäre, dass Java nicht installiert ist.

      Um das herauszufinden:
      1. Windows Taste > cmd
      2. Java -version ausführen.

      Entweder wird dir nun (wenn korrekt installiert) die aktuell installierte Java Version angezeigt oder du erhältst eine Fehlermeldung. – In diesem Fall solltest du Java installieren: https://www.java.com/de/download/

      LG

      1. upps, mein Kommentar war nicht ganz präzise wie sich nach weiterer Recherche rausstellt. Ich musste das Java Development Kit noch auf dem Mac installieren. Juhu, damit sind zumindest die beiden Fehlerzeilen "Unable to find any JVMs matching version "(null)".
        No Java runtime present, try –request to install." nicht mehr da … Leider immernoch weit entfernt davon, das Skript zum Laufen zu bringen

        1. blank

          Um die nächsten Errors anzugehen, wurden alle Libraries die im Script genutzt werden,
          library(tidyverse)
          library(lubridate)
          library(stringr)
          library(xlsx)
          library(httr)
          , auch vorher beispielsweise für xlsx mittels: install.packages("xlsx") installiert?

          Des weiteren haben sich im Screaming Frog die Exporte geändert. Die erste Zeile muss beim Einlesen nun nicht mehr übersprungen werden also sollte das Argument , skip = 1 beim Einlesen der Crawls in der Funktion read_csv herausgenommen werden.

          1. Das ist auch ein wertvoller Tipp! Hmm, also anscheinend sind die nicht installiert. Na dann mache ich mich mal da ran … Danke abermals

          2. Hmm, so langsam werden die Fehler tatsächlich weniger.

            > library(tidyverse)
            Fehler: package or namespace load failed for ‘tidyverse’ in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]):
            es gibt kein Paket namens ‘scales’

            Woran kann das denn jetzt schon wieder liegen?

          3. blank

            Moin, das liegt daran, dass die Library scales nicht installiert ist. Kleiner Tipp, Fehlermeldungen kann man meist recht gut googlen. 😉 LG

  6. Hallo und vielen Dank für die tolle Anleitung 🙂
    Bei mir läuft das Skript leider auch nicht und ich weiß absolut nicht, woran das liegen könnte.
    skip = 1 habe ich bereits wie oben beschrieben aus dem Code entfernt.

    Nach dem Punkt "Einlesen der Crawls" kommt bei mir die folgende Fehlermeldung:
    Parsed with column specification:
    cols(
    Internal - All = col_character()
    )
    Warnung: 159 parsing failures.
    row col expected actual file
    1 — 1 columns 43 columns 'C:/Users/Kunde/Documents/Kunde1/Crawls//kunde_2019-11-19_internal_all.csv'
    2 — 1 columns 43 columns 'C:/Users/Kunde/Documents/Kunde1/Crawls//kunde_2019-11-19_internal_all.csv'
    3 — 1 columns 43 columns 'C:/Users/Kunde/Documents/Kunde1/Crawls//kunde_2019-11-19_internal_all.csv'
    … … ……… ………. …………………………………………………………………………….
    See problems(…) for more details.

    Parsed with column specification:
    cols(
    Internal - All = col_character()
    )
    Warnung: 161 parsing failures.
    row col expected actual file
    1 — 1 columns 43 columns 'C:/Users/Kunde/Documents/Kunde1/Crawls//kunde_2019-11-27_internal_all.csv'
    2 — 1 columns 43 columns 'C:/Users/Kunde/Documents/Kunde1/Crawls//kunde_2019-11-27_internal_all.csv'
    3 — 1 columns 43 columns 'C:/Users/Kunde/Documents/Kunde1/Crawls//kunde_2019-11-27_internal_all.csv'
    … … ……… ………. …………………………………………………………………………….
    See problems(…) for more details.

    Dann folgt nach dem Punkt "Ein bisschen aufräumen" die folgende Fehlermeldung:
    Fehler in stri_detect_regex(string, pattern, negate = negate, opts_regex = opts(pattern)) :
    argument str should be a character vector (or an object coercible to)

    Zum Schluss bekomme ich am Ende nur die folgende Info:
    Fehler in eval(lhs, parent, parent) :
    Objekt 'internal_all_html' nicht gefunden

    Ich kann mir vorstellen, dass es am Einlesen der Dokumente liegen könnte, aber ich verstehe nicht, welches Problem es hierbei gibt.

    Könnt ihr mir evtl. Tipps geben, woran das liegen könnte?

    Vielen Dank und liebe Grüße
    Sandra

    1. blank

      Hi Sandra,

      > cols(
      Internal – All = col_character()
      )

      das sieht für mich so aus, dass du einen alten Crawl-Export laden willst, der in der ersten Zeile noch die Angabe über die Art des Crawls enhält. Entweder den Frosch updaten und noch mal exportieren oder das skip = 1 zum Überspringen der ersten Zeil wieder einfügen.

      LG

      1. Hallo Patrick,

        vielen Dank für Deine Antwort.
        Ich habe beides versucht, wobei ich das Gefühl habe, dass ich durch das Screaming-Frog-Update der Lösung näher komme.

        Nun (mit der neuen Version des Screaming Frogs, ohne Einfügen von skip = 1) wird mir nach "Einlesen der Crawls" die folgende Fehlermeldung angezeigt:
        Parsed with column specification:
        cols(
        .default = col_double(),
        Address = col_character(),
        Content = col_character(),
        Status = col_character(),
        Indexability = col_character(),
        Indexability Status = col_character(),
        Title 1 = col_character(),
        Meta Description 1 = col_character(),
        Meta Keyword 1 = col_character(),
        H1-1 = col_character(),
        H2-1 = col_character(),
        H2-2 = col_character(),
        Meta Robots 1 = col_character(),
        X-Robots-Tag 1 = col_logical(),
        Meta Refresh 1 = col_logical(),
        Canonical Link Element 1 = col_character(),
        rel="next" 1 = col_logical(),
        rel="prev" 1 = col_logical(),
        HTTP rel="next" 1 = col_logical(),
        HTTP rel="prev" 1 = col_logical(),
        Link Score = col_logical()
        # … with 5 more columns
        )
        See spec(…) for full column specifications.
        Parsed with column specification:
        cols(
        .default = col_double(),
        Address = col_character(),
        Content = col_character(),
        Status = col_character(),
        Indexability = col_character(),
        Indexability Status = col_character(),
        Title 1 = col_character(),
        Meta Description 1 = col_character(),
        Meta Keyword 1 = col_character(),
        H1-1 = col_character(),
        H2-1 = col_character(),
        H2-2 = col_character(),
        Meta Robots 1 = col_character(),
        X-Robots-Tag 1 = col_logical(),
        Meta Refresh 1 = col_logical(),
        Canonical Link Element 1 = col_character(),
        rel="next" 1 = col_logical(),
        rel="prev" 1 = col_logical(),
        HTTP rel="next" 1 = col_logical(),
        HTTP rel="prev" 1 = col_logical(),
        Link Score = col_logical()
        # … with 5 more columns
        )
        See spec(…) for full column specifications.

        Das Skript endet dann mit der Fehlermeldung:
        Fehler: Objekt 'size_new' nicht gefunden

        Kann das an der Bezeichnung der "size"-Spalte liegen?
        Mir ist schon aufgefallen, dass die alte Spalte "size" im neuen Screaming Frog jetzt "Size (bytes)" heißt. Im Skript ist aber nur von "size" die Rede.
        Ich habe schon versucht, den Code entsprechend anzupassen, komme aber mit den Klammern und Leerzeichen in der neuen Bezeichnung nicht zurecht. Wenn ich im Code "size" in "size_(bytes)" ändere, kommen lauter weitere Fehlermeldungen.

        Könnt ihr mir nochmal weiterhelfen?

        Vielen Dank und liebe Grüße
        Sandra

  7. Wirklich sehr cool! Unendlich viel Liebe für diese Arbeitserleichterung. Genau so etwas hab ich immer gesucht, sind die Kunden doch selten so gut einem alle Änderungen zuverlässig mitzuteilen.

    Für neue Nutzer wäre es praktisch, auf GitHub eine leicht abgeänderte Version (mit Zeile 1, mit umbenannter "Size (bytes)"-Spalte) hochzuladen, um auch für die aktuellen ScreamingFrog-Exporte zu passen.

    1. blank

      Servus Jon,
      danke, danke. 🙂 Ja, die Anpassung muss ich mal angehen. Ich schieb es nur immer vor mir her, weil ich das Skript mittlerweile weiter aufgebohrt habe und eigentlich eine neuere Version bereitstellen könnte. Nur muss ich dann wieder was schreiben und so liegt es gerade halt leider liegen….

  8. Hallo David,
    danke für die Anleitung. Habe sie soweit durchgearbeitet.
    In Schritt 9 bei der Aufgabenverwaltung scheint euer CMS die doppelten "–" durch einfache "-" ersetzt zu haben. Hab da die Scheduling Funktion von SF verwendet und dann die Werte entsprechend eurer Vorgabe geändert. "–project-name" scheint SF nicht zu verstehen.

    Nachdem ich alles eingestellt habe und das Crawling etc. funktionieren, bekomme ich bei RStudio folgenden Fehler:

    Nur bei R habe ich ein Problem:

    "Attache Paket: 'lubridate'

    The following object is masked from 'package:base':

    date

    Fehler in matrix(NA_character_, nrow = nrow(indt), ncol = Ncol) :
    ungültiger 'ncol' Wert (zu groß oder NA)
    Ruft auf: %>% … <Anonymous> -> <Anonymous> -> lapply -> FUN -> matrix
    Zusätzlich: Warnmeldungen:
    1: In max(unlist(lapply(SetUp, function(y) y[["Mat"]][, 2]), use.names = FALSE)) :
    kein nicht-fehlendes Argument für max; gebe -Inf zurück
    2: In matrix(NA_character_, nrow = nrow(indt), ncol = Ncol) :
    NAs introduced by coercion to integer range
    Ausführung angehalten"


    Java neuinstalliert etc., aber leider kommt der Fehler noch immer.

    Hast du vielleicht einen Tipp für mich?

    Danke vielmals.

    LG

    Sercan

    1. blank

      Hi Sercan

      Dieser Fehler ist typisch, wenn die CSV-Dateien nicht richtig eingelesen/gefunden werden konnten.
      Sprich: Das Skript an der Stelle #Split File Paths keine Pfade zum Splitten hat, da die Variable "files" leer ist.
      Am besten einmal sicherstellen, dass die Pfade zu deinen CSV Dateien unter # VARS richtig angegeben sind. Sonst gerne nochmal melden 🙂

      LG
      David

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.