Bienvenue dans la documentation de développement de MusiqueBox
Ce site est (ou devrait être) un tutoriel et une documentation conviviale pour les débutants qui souhaitent utiliser ou écrire des services pour le MusiqueBox Extractor. Il contient également plusieurs notes sur la manière de maintenir MusiqueBox. C’est un complément à notre documentation Jdoc générée automatiquement.
Veuillez noter que cette documentation en est à ses débuts, donc toute aide ou retour est toujours apprécié
Introduction
Le MusiqueBox Extractor est un framework Java permettant de récupérer des données sur les sites de plateformes vidéo de manière à les rendre accessibles comme une API classique. L’extracteur est le cœur de l’application MusiqueBox pour Android, qui permet d’accéder à YouTube et à d’autres services de streaming. Il est entièrement indépendant des plateformes qu’il prend en charge, et est également disponible pour d’autres plateformes supplémentaires.
L’avantage principal de ce framework est qu’il s’occupe du processus d’extraction, de la gestion des erreurs, etc., afin que vous puissiez vous concentrer sur ce qui est vraiment important : l’extraction des données du site. Il vise à permettre aux créateurs de scrapers pour les services de streaming de produire les meilleurs résultats avec un minimum de code.
Avant de Commencer
Ces documents vous guideront dans le processus de compréhension ou de création de votre propre service Extractor, qui permettra à MusiqueBox d’accéder à des services de streaming supplémentaires, tels que ceux déjà pris en charge comme YouTube et MusiqueBox. La documentation complète se compose de cette page et d’une configuration Jdoc qui explique le concept général du MusiqueBox Extractor.
IMPORTANT !!! Il est possible que cette documentation ne soit pas la meilleure que vous ayez jamais lue, alors n’hésitez pas à signaler toute faute d’orthographe, toute partie incomplète ou tout ce que vous ne comprenez pas. Nous sommes une communauté ouverte et nous acceptons volontiers toute aide 🙂
Configuration de Votre Environnement de Développement
Tout d’abord, vous devez remplir les conditions suivantes pour écrire votre propre service.
Ce que Vous Devez Savoir :
- Une compréhension de base de Git
- Une bonne connaissance de Java
- Une solide compréhension des technologies web
- Une connaissance de base des tests unitaires et de JUnit
- Une compréhension approfondie de la façon de contribuer au projet MusiqueBox
Outils/Programmes Dont Vous Aurez Besoin :
- Un environnement de développement (IDE) prenant en charge :
- Git
- Java 8
- Gradle
- Tests unitaires
- IntelliJ IDEA Community (fortement recommandé, mais pas obligatoire)
- Un compte GitHub
- Beaucoup de patience et d’excitation ;D
Après vous être assuré que toutes ces conditions sont remplies, forkez le dépôt MusiqueBox Extractor à l’aide du bouton « Fork ». Cela vous permet d’avoir un dépôt personnel sur lequel développer. Ensuite, clonez ce dépôt dans le dossier local où vous souhaitez travailler. Puis, importez le projet cloné dans votre IDE et exécutez-le. Si tous les tests passent au vert, vous avez tout fait correctement ! Vous pouvez passer au chapitre suivant.
Importer le MusiqueBox Extractor dans IntelliJ IDEA
Si vous utilisez IntelliJ IDEA, voici la méthode facile pour importer l’extracteur MusiqueBox. Si vous ne la connaissez pas, voici comment procéder :
- Clonez l’extracteur sur votre ordinateur localement avec
git clone
. - Lancez IntelliJ IDEA et cliquez sur Importer un projet.
- Sélectionnez le répertoire racine du MusiqueBox Extractor.
- Sélectionnez « Importer un projet à partir d’un modèle externe », puis choisissez Gradle.
- Dans la fenêtre suivante, sélectionnez « Utiliser la configuration de la tâche ‘wrapper’ de Gradle ».
Exécuter les tests dans Android Studio/IntelliJ IDEA
Allez dans Exécuter > Modifier les configurations > Ajouter une nouvelle configuration et sélectionnez Gradle. En tant que projet Gradle, sélectionnez MusiqueBox Extractor. Comme tâche, ajoutez test. Enregistrez, et vous devriez pouvoir exécuter les tests.
Critères d’Inclusion pour les Services
Après avoir créé votre propre service, vous devrez le soumettre au dépôt MusiqueBox Extractor. Cependant, pour que vos modifications soient incluses, vous devez suivre ces règles :
- Respectez nos lignes directrices de contribution au code.
- N’envoyez pas de services qui présentent des contenus que nous n’autorisons pas sur MusiqueBox.
- Vous devez être prêt à maintenir votre service après sa soumission.
- Soyez patient et effectuez les modifications demandées si un de nos mainteneurs rejette votre code.
Contenus Autorisés
- Tout contenu qui ne figure pas sur la liste des contenus interdits.
- Tout type de contenu pour adultes ou NSFW (Not Safe For Work) qui ne viole pas la législation française. Cependant, les services pornographiques ne seront pas ajoutés à l’application officielle MusiqueBox.
- La publicité, sous réserve d’approbation préalable.
Contenus Non Autorisés
- Contenu classé NSFL (Not Safe For Life).
- Contenu interdit par la loi française (sexualisation des mineurs, toute forme de violence, violations des droits de l’homme, etc.).
- Médias protégés par des droits d’auteur, sans le consentement du détenteur des droits d’auteur ou de l’éditeur.
Concept de l’Extracteur
Le modèle Collecteur/Extracteur
Avant de commencer à coder votre propre service, vous devez comprendre le concept de base de l’extracteur lui-même. Il existe un modèle que vous retrouverez dans tout le code, appelé modèle collecteur/extracteur. L’idée derrière ce modèle est que l’extracteur produit des fragments de données, et le collecteur les assemble dans un format lisible pour le front-end. Le collecteur contrôle également le processus de parsing et gère les erreurs. Si l’extracteur échoue à un moment donné, le collecteur décide s’il doit continuer ou non le parsing. Cela nécessite que l’extracteur soit composé de plusieurs méthodes, une pour chaque champ de données que le collecteur souhaite avoir. Les collecteurs sont fournis par MusiqueBox. Vous devez vous occuper des extracteurs.
Utilisation dans le Front-End
Un appel typique pour récupérer des données depuis un site web ressemblerait à ceci :
Info info;
try {
// Créer un nouvel extracteur avec un contexte donné en paramètre.
Extractor extractor = new Extractor(some_meta_info);
// Récupérer les données de l'extracteur et construire un package d'information.
info = Info.getInfo(extractor);
} catch(Exception e) {
// gérer les erreurs lorsque le collecteur décide d'arrêter l'extraction
}
Implémentation Typique d’un Extracteur de Données
L’implémentation classique d’un extracteur de données ressemblerait à ceci :
class MyExtractor extends FutureExtractor {
public MyExtractor(RequiredInfo requiredInfo, ForExtraction forExtraction) {
super(requiredInfo, forExtraction);
...
}
@Override
public void fetch() {
// Récupérer les données de la page ici
}
@Override
public String someDataField()
throws ExtractionException { // L'exception doit être lancée si quelque chose échoue
// Obtenir l'information et la retourner
}
... // Autres champs de données
}
Modèle Collecteur/Extracteur pour les Listes
L’information peut être représentée sous forme de liste. Dans MusiqueBox, une liste est représentée par un InfoItemsCollector. Ce collecteur assemble une liste d’InfoItem. Pour chaque élément à extraire, un nouvel extracteur doit être créé et donné au collecteur via la méthode commit().
Si vous implémentez une liste dans votre service, vous devez implémenter un InfoItemExtractor, capable de récupérer les données pour un seul élément d’information. Cet extracteur sera ensuite soumis au InfoItemsCollector qui recueillera les types d’InfoItems que vous souhaitez générer.
ListExtractor
Il y a quelques points supplémentaires à savoir sur les listes :
- Lorsqu’un site de streaming affiche une liste d’éléments, il offre généralement des informations supplémentaires telles que son titre, une vignette et son créateur. Ces informations sont appelées en-tête de liste.
- Les sites web qui affichent une longue liste d’éléments ne chargent généralement qu’une partie de celle-ci. Pour obtenir plus d’éléments, vous devrez peut-être cliquer sur un bouton de page suivante ou faire défiler vers le bas.
Ces problèmes sont résolus par le ListExtractor, qui s’occupe d’extraire les métadonnées supplémentaires de la liste, et de découper les listes en plusieurs pages appelées InfoItemsPages. Chaque page a sa propre URL et doit être extraite séparément.
Pour extraire les informations d’en-tête d’une liste, un ListExtractor fonctionne comme un extracteur régulier. Pour gérer les InfoItemsPages, il ajoute des méthodes telles que :
- getInitialPage() : renvoie la première page d’InfoItems.
- getNextPageUrl() : si une seconde page d’InfoItems est disponible, cela renverra l’URL correspondante.
- getPage() : renvoie une InfoItemsPage en fonction de l’URL obtenue avec getNextPageUrl() de la page précédente.
La raison pour laquelle la première page est traitée différemment est que de nombreux sites, tels que YouTube, chargent la première page d’éléments comme une page web régulière, mais toutes les autres sous forme de requêtes AJAX.
Implémentation de Référence Simplifiée d’un List Extractor
Voici une implémentation simplifiée d’un ListExtractor qui extrait uniquement les pages, sans métadonnées :
class MyListExtractor extends ListExtractor {
...
private Document document;
...
public InfoItemsPage<SomeInfoItem> getPage(String pageUrl)
throws ExtractionException {
SomeInfoItemCollector collector = new SomeInfoItemCollector(getServiceId());
document = myFunctionToGetThePageHTMLWhatever(pageUrl);
// Extraction simple des éléments de la liste
for(final Element li : document.children()) {
collector.commit(new InfoItemExtractor() {
@Override
public String getName() throws ParsingException {
...
}
@Override
public String getUrl() throws ParsingException {
...
}
...
});
}
return new InfoItemsPage<SomeInfoItem>(collector, myFunctionToGetTheNextPageUrl(document));
}
public InfoItemsPage<SomeInfoItem> getInitialPage() {
// Le document est initialisé par la fonction fetch()
return getPage(getTheCurrentPageUrl(document));
}
...
}
Concept du LinkHandler
Le LinkHandler représente des liens vers des ressources comme des vidéos, des requêtes de recherche, des chaînes, etc. L’idée est qu’une vidéo peut avoir plusieurs liens qui y pointent, mais un seul ID unique qui la représente.
Notes importantes sur le LinkHandler
- Un LinkHandler simple contiendra l’URL par défaut, l’ID, et l’URL d’origine.
- Les LinkHandlers sont en lecture seule.
- Les LinkHandlers sont également utilisés pour déterminer quelle partie de l’extracteur peut gérer un certain lien.
- Pour obtenir un LinkHandler, vous devez appeler
fromUrl()
oufromId()
depuis la LinkHandlerFactory correspondante. - Chaque type de ressource a sa propre LinkHandlerFactory, par exemple : YoutubeStreamLinkHandler, YoutubeChannelLinkHandler, etc.
Utilisation
Voici un exemple typique pour obtenir un LinkHandler :
LinkHandlerFactory myLinkHandlerFactory = new MyStreamLinkHandlerFactory();
LinkHandler myVideo = myLinkHandlerFactory.fromUrl("https://my.service.com/the_video");
Implémentation
Pour utiliser le LinkHandler dans votre service, vous devez redéfinir la LinkHandlerFactory appropriée, par exemple :
class MyStreamLinkHandlerFactory extends LinkHandlerFactory {
@Override
public String getId(String url) throws ParsingException {
// Retourner l'ID en fonction de l'URL.
}
@Override
public String getUrl(String id) throws ParsingException {
// Retourner l'URL en fonction de l'ID donné.
}
@Override
public boolean onAcceptUrl(String url) throws ParsingException {
// Retourner true si cette LinkHandlerFactory peut gérer ce type de lien.
}
}
ListLinkHandler et SearchQueryHandler
Les ressources basées sur des listes, comme les chaînes et les playlists, peuvent être triées et filtrées. Par conséquent, ces types de ressources n’utilisent pas seulement un LinkHandler, mais une classe appelée ListLinkHandler, qui hérite de LinkHandler et ajoute le champ ContentFilter, utilisé pour filtrer par type de ressource (comme un flux ou une playlist), et SortFilter, utilisé pour trier par nom, date ou nombre de vues.
!!ATTENTION!! Lorsque vous implémentez un filtre de contenu, soyez prudent : Aucun filtre sélectionné équivaut à tous les filtres sélectionnés. Si vous obtenez une liste de filtres de contenu vide dans votre extracteur, assurez-vous de tout retourner. Utilisez des instructions « if » comme contentFilter.contains("video") || contentFilter.isEmpty()
.
Les ListLinkHandler sont également créés en redéfinissant la ListLinkHandlerFactory. En plus des méthodes abstraites héritées de la LinkHandlerFactory, vous pouvez redéfinir getAvailableContentFilter() et getAvailableSortFilter() pour indiquer au front-end quels types de filtres votre service prend en charge.
SearchQueryHandler
Vous ne pouvez pas pointer une requête de recherche avec un ID, comme vous pouvez le faire avec une playlist ou une chaîne, tout simplement parce qu’une même requête de recherche peut avoir un résultat différent en fonction du pays ou du moment où vous envoyez la requête. C’est pourquoi l’idée d’un « ID » est remplacée par une SearchString dans le SearchQueryHandler. Ceux-ci fonctionnent comme des ListLinkHandler réguliers, sauf que vous n’avez pas à implémenter les méthodes onAcceptUrl()
et getId()
lorsque vous redéfinissez le SearchQueryHandlerFactory.
Implémentation d’un Service
Les services, ou plutôt les connecteurs de services, sont les parties de MusiqueBox qui communiquent avec un service réel, comme YouTube. Cette page décrit comment vous pouvez implémenter et ajouter vos propres services à l’extracteur. Assurez-vous d’avoir bien lu et compris les concepts d’extracteurs et de LinkHandler avant de continuer.
Parties Obligatoires et Optionnelles
Votre service n’a pas besoin d’implémenter toutes les fonctionnalités ; certaines parties sont optionnelles. Cela est dû au fait que tous les services ne prennent pas en charge les mêmes fonctionnalités. Par exemple, il se peut qu’un certain service ne prenne pas en charge les chaînes. Dans ce cas, vous pouvez omettre l’implémentation des chaînes, et faire en sorte que la méthode correspondante de votre implémentation de StreamingService renvoie null
. Le frontend gérera l’absence de chaînes.
Cependant, si vous commencez à implémenter une des parties optionnelles de la liste ci-dessous, vous devrez implémenter toutes ses parties/classes. MusiqueBox plantera si vous implémentez uniquement l’extracteur pour un élément de la liste (par exemple une chaîne), mais pas l’extracteur de chaîne lui-même.
Les Parties d’un Service :
- Tête de Service
- Stream
- Recherche
- Playlist (optionnel)
- Chaîne (optionnel)
- Kiosque (optionnel)
Bibliothèques Autorisées
L’extracteur de MusiqueBox inclut déjà de nombreux outils et bibliothèques externes qui facilitent l’extraction. Pour certaines tâches spécifiques (mineures), l’utilisation de Regex est autorisée. Vous pouvez consulter le Parser, qui vous donnera un petit coup de pouce à ce sujet. Utilisez Regex avec précaution !!! Évitez-le autant que possible. Il vaut mieux nous demander d’introduire une nouvelle bibliothèque plutôt que d’utiliser trop souvent Regex.
- Parsing HTML/XML : jsoup
- Parsing JSON : nanojson
- Parsing/Exécution de JavaScript : Mozilla Rhino
- Détection de liens dans les chaînes de texte : AutoLink
Si vous devez introduire de nouvelles bibliothèques, merci de nous en informer avant de le faire.
Tête de Service
Si vous souhaitez créer un nouveau service, vous devez d’abord créer un nouveau package sous org.MusiqueBox.services, avec le nom de votre service comme nom de package.
Parties Obligatoires à Implémenter :
- StreamingService
- ServiceInfo
StreamingService est une classe de fabrique qui renverra des objets de toutes les parties importantes de votre service. Chaque extracteur, gestionnaire, et type d’info que vous ajoutez et qui devrait faire partie de votre implémentation doit être instancié à l’aide d’une instance de cette classe. Vous pouvez la voir comme une fabrique pour tous les objets de votre implémentation.
ServiceInfo renverra certaines métadonnées sur votre service telles que le nom, les capacités, le nom de l’auteur et son adresse e-mail pour d’éventuels problèmes de maintenance. Après avoir étendu cette classe, vous devez retourner une instance de celle-ci via votre implémentation de StreamingService.getServiceInfo().
Une fois ces deux classes étendues, vous devez ajouter votre StreamingService à la ServiceList de MusiqueBox. De cette façon, votre service deviendra une partie officielle de l’extracteur MusiqueBox. Chaque service a un ID, qui est défini lors de la création de cette liste. Vous devez définir cet ID en l’inscrivant dans le constructeur. Lorsque vous ajoutez votre service, donnez-lui simplement l’ID du dernier service de la liste, incrémenté de un.
Stream
Les streams sont considérés comme des entités uniques de vidéo ou d’audio. Ils ont des métadonnées comme un titre, une description, des vidéos connexes, une vignette, et des commentaires. Pour obtenir l’URL des données du stream ainsi que ses métadonnées, on utilise le StreamExtractor. La LinkHandlerFactory représentera un lien vers un tel stream. StreamInfoItemExtractor extraira un élément dans une liste d’éléments représentant ces streams, comme un résultat de recherche ou une playlist. Puisque chaque service de streaming fournit évidemment des streams, il est nécessaire de l’implémenter. Sinon, votre service serait inutile 🙂
Parties Obligatoires à Implémenter :
- StreamExtractor
- StreamInfoItemExtractor
- LinkHandlerFactory
Recherche
Le SearchExtractor doit également être implémenté. Il prendra une requête de recherche représentée par SearchQueryHandler et renverra une liste de résultats de recherche. Étant donné que de nombreux services prennent en charge les suggestions lors de la saisie, vous voudrez peut-être aussi implémenter un SuggestionExtractor. Cela permettra au frontend d’afficher également des suggestions pendant la saisie.
Parties Obligatoires à Implémenter :
- SearchExtractor
- SearchQueryHandlerFactory
- SuggestionExtractor (optionnel)
Playlist
Les playlists sont des listes de streams fournies par le service (vous n’avez pas à vous soucier des playlists sauvegardées localement, elles seront gérées par le frontend). Une playlist ne peut contenir que des StreamInfoItems, mais aucun autre type d’InfoItem.
Parties Obligatoires à Implémenter :
- PlaylistExtractor
- PlayListInfoItemExtractor
- ListLinkHandlerFactory
Chaîne
Une chaîne est essentiellement une playlist, à la différence qu’elle ne représente pas uniquement une simple liste de streams, mais aussi un utilisateur, une chaîne ou toute entité pouvant être représentée comme un utilisateur. C’est pourquoi les métadonnées prises en charge par le ChannelExtractor diffèrent de celles d’une playlist.
Parties Obligatoires à Implémenter :
- ChannelExtractor
- ChannelInfoItemExtractor
- ListLinkHandlerFactory
Kiosque
Un kiosque est une liste d’InfoItems qui seront affichés sur la page principale de MusiqueBox. Un kiosque ressemble beaucoup au contenu affiché sur la page principale d’une plateforme vidéo. Un kiosque pourrait être quelque chose comme « Top 20 », « Classements », « Actualités », « Sélection des Créateurs », etc. Les kiosques sont parfois controversés ; de nombreuses personnes peuvent ne pas les apprécier. Si vous faites partie de ceux-là, pensez tout de même à vos utilisateurs et évitez de refuser le support pour cette fonctionnalité. Votre service semblerait vide si vous le sélectionnez et qu’aucune vidéo n’est affichée. Vous ne devez pas non plus outrepasser la préférence de l’utilisateur, car les utilisateurs de MusiqueBox peuvent décider dans les paramètres s’ils veulent ou non voir la page du kiosque.
Kiosques Multiples
La plupart des services implémenteront plus d’un kiosque. Un service pourrait avoir un « Top 20 » pour différentes catégories comme « Musique Country », « Techno », etc. C’est pourquoi l’extracteur vous permettra d’implémenter plusieurs KioskExtractors. Étant donné que les différentes pages de kiosques peuvent également différer dans leur structure HTML, chaque page que vous souhaitez prendre en charge doit être implémentée comme son propre KioskExtractor. Cependant, si les pages sont similaires, vous pouvez utiliser la même implémentation, mais définir le type de page lorsque vous instanciez votre KioskExtractor via la KioskList.KioskExtractorFactory.
Chaque kiosque que vous implémentez doit être ajouté à votre KioskList, que vous retournerez via votre implémentation de StreamingService.
Il est également important de définir le kiosque par défaut. Il s’agit du kiosque qui sera affiché au premier démarrage de votre service.
@Override
public KioskList getKioskList() throws ExtractionException {
KioskList list = new KioskList(getServiceId());
list.addKioskEntry(new KioskList.KioskExtractorFactory() {
@Override
public KioskExtractor createNewKiosk(StreamingService streamingService,
String url,
String id,
Localization local)
throws ExtractionException {
return new YoutubeTrendingExtractor(YoutubeService.this,
new YoutubeTrendingLinkHandlerFactory().fromUrl(url), id, local);
}
}, new YoutubeTrendingLinkHandlerFactory(), "Trending");
list.setDefaultKiosk("Trending");
return list;
}