Skip to content

Parsing et utilitaires

Écrire un extracteur consiste surtout à transformer une réponse en champs de modèle. Le package utils est la boîte à outils, et deux bibliothèques font le gros du travail.

JSON : nanojson

Le parsing JSON utilise nanojson (com.grack.nanojson) : JsonObject, JsonArray, JsonParser, JsonWriter. Un parse typique :

java
JsonObject root = JsonParser.object().from(downloader.get(url).responseBody());
JsonArray items = root.getArray("results");
for (int i = 0; i < items.size(); i++) {
    JsonObject item = items.getObject(i);
}

JsonUtils ajoute un accès par chemin pointé pour éviter d'enchaîner getObject à la main, et lève une ParsingException (plutôt que de retourner null) quand un chemin est manquant :

java
JsonUtils.getString(root, "data.items.0.title");
JsonUtils.getArray(root, "contents.section.items");
JsonUtils.toJsonObject(responseBody);   // parse et enveloppe les erreurs

HTML : jsoup

Le scraping HTML utilise jsoup (org.jsoup) : Jsoup.parse, Document, Element, Elements.

java
Document doc = Jsoup.parse(downloader.get(url).responseBody());
for (Element e : doc.getElementsByClass("writing")) {
    collector.commit(new MyCommentItemExtractor(e));
}

Regex : Parser

Parser enveloppe java.util.regex avec des helpers adaptés à l'extracteur, qui lèvent une Parser.RegexException (une ParsingException) en l'absence de correspondance, de sorte qu'une correspondance échouée soit une erreur d'extraction, pas un null silencieux :

java
Parser.matchGroup1("v=([\\w-]+)", url);
Parser.matchGroup(pattern, input, 2);
Parser.matchGroup1MultiplePatterns(patterns, input);   // en essaie plusieurs, la première qui touche
Parser.isMatch(pattern, input);

Helpers du quotidien : Utils

Utils est le fourre-tout vers lequel on se tourne en permanence :

java
Utils.isNullOrEmpty(str | collection | map);
Utils.removeNonDigitCharacters("1,234 views");   // -> "1234"
Utils.mixedNumberWordToLong("1.2M");             // compteurs suffixés -> long
Utils.getBaseUrl(url);  Utils.getQueryValue(url, "v");
Utils.replaceHttpWithHttps(url);  Utils.encodeUrlUtf8(s);  Utils.decodeUrlUtf8(s);
Utils.EMPTY_STRING;

Exécuter du JavaScript

Quand un service a besoin d'exécuter le JS du player (le cas de YouTube, voir Dans YouTube), JavaScript enveloppe Rhino :

java
JavaScript.compileOrThrow(fn);
JavaScript.run(fn, "functionName", args...);

et le package jsextractor (Lexer, JavaScriptExtractor.matchToClosingBrace) extrait un corps de fonction équilibré depuis du code minifié. À noter que dans ce fork, le chemin de signature YouTube délègue le plus souvent à une API de décodage distante plutôt que d'exécuter ce JS localement.

Mise en cache des manifestes

ManifestCreatorCache est un petit cache borné et sérialisable que les créateurs de manifeste DASH utilisent pour qu'une requête répétée ne reconstruise pas le même manifeste à partir de zéro.