[JAVA] Créer une base de données de tous les livres qui ont circulé au Japon au siècle dernier

0. Introduction (lecteurs cibles, etc.)

C'est un titre de pêche. Je suis désolé. En fait, nous allons créer une base de données de tous les ** «699 livres TV / Radio» qui ont circulé au Japon au cours du siècle dernier. De plus, ** un grand nombre d'accès automatique au serveur de la Bibliothèque nationale de l'Assemblée nationale sera effectué, veuillez donc le faire à vos propres risques **.

Public cible

1. Expérience

Si vous effectuez une recherche détaillée avec la Bibliothèque nationale de l'Assemblée nationale Rechercher et recherchez uniquement avec le code de classification «699», Vous pouvez rechercher tous les livres à la télévision et à la radio de 1925 à 2020. Mais malheureusement, seuls les 500 premiers résultats peuvent être vus en une seule recherche. (Le 501e et les éléments suivants ne sont pas affichés dans les résultats de la recherche en premier lieu) Vous pouvez également affiner votre recherche par année de publication, mais dans n'importe quelle année de 1925 à 2020, le nombre de résultats ne dépassait pas 500 (en un an). Donc, si vous faites une recherche et obtenez les résultats chaque année, cela prendra du temps, mais essayons de voir tous les résultats.

1-1. Expérience 1 sur la conception du robot d'exploration ndl

Un robot d'exploration est un programme qui collecte des informations sur le Web. Concevons un programme qui recueille des informations à partir de la recherche de la Bibliothèque nationale de l'Assemblée nationale en l'appelant un "crawler ndl". Il peut être conçu par la procédure suivante.

  1. Utilisez la recherche de la Bibliothèque nationale de la diététique depuis votre navigateur
  2. Saisissez tous les éléments de la recherche avancée en caractères alphanumériques et exécutez la recherche.
  3. Vérifiez quel élément correspond à quel paramètre en comparant avec le paramètre get
  4. Concevez le programme en vous basant sur les indices obtenus jusqu'à 3.

1-1-1. Étapes 1 à 3

Premièrement, lors de la recherche dans les conditions illustrées à la figure 1.1.1.1, l'url des résultats de la recherche (affichage de la gorge) était la suivante. https://iss.ndl.go.jp/books?datefrom=1234&place=place&rft.isbn=isbn&rft.title=title&dateto=5678&rft.au=author&subject=subject&do_remote_search=true&rft.pub=publisher&display=thumbnail&ndc=genre&search_mode=advanced

image.png Figure 1.1.1.1 url Critères de recherche pour l'observation des paramètres

Une comparaison montre que le tableau 1.1.1.1 le montre. (Cependant, seul le "numéro de la page de résultats" a été confirmé dans un autre essai.)

Tableau 1.1.1.1 Paramètres d'url de recherche de la Bibliothèque nationale du Parlement

article Paramètres valeur
Titre rft.title
Rédacteur auteur rft.au
l'éditeur rft.pub
Point de départ de la section année de publication datefrom
Point final de la section de l'année de publication dateto
matière subject
Symbole de classification ndc
ISBN/ISSN rft.isbn
Place de publication place
Numéro de la page de résultats page
Afficher les résultats sous forme de vignettes display thumbnail
A part ça, je vais le garder pour le moment 1/2 do_remote_search true
A part ça, je vais le garder pour le moment 2/2 search_mode advance

1-1-2. Étape 4 (Conception du robot)

Créez le package java ndl et créez-y le NDL Rawler.java suivant. (La classe Parser qui apparaît dans le code est décrite dans la section 1-1-3. En bref, le contenu de la page de résultat passée au constructeur est moulé en csv avec la méthode parse (). La méthode has15 () retourne une valeur booléenne indiquant si le résultat est 15. ) (La classe WebGetter qui apparaît dans le code sert simplement à récupérer la source html sur Internet avec la méthode get)

NDLCrawler.java


package ndl;

import java.io.*;
import java.net.*;

public class NDLCrawler
{
	private String url = "https://iss.ndl.go.jp/books?",
	title="", author="", publisher="", yearfrom="",yearto="", subject="", bunrui="", isbn_issn="", place="";
	public void setTitle(String str){title=str;} public void setAuthor(String str){author=str;} public void setPublisher(String str){publisher=str;} public void setYearfrom(String str){yearfrom=str;} public void setYearto(String str){yearto=str;} public void setSubject(String str){subject=str;} public void setBunrui(String str){bunrui=str;} public void setIsbn_issn(String str){isbn_issn=str;} public void setPlace(String str){place=str;}
	public String crawle()
	{
		System.out.println("Démarrage du robot d'exploration");
		String csv="";
		String urlWithGet = url+ "rft.title=" + title + "&rft.au=" + author + "&rft.pub=" + publisher + "&datefrom=" + yearfrom + "&dateto=" + yearto + "&subject=" + subject + "&ndc=" + bunrui + "&rft.isbn=" + isbn_issn + "&place=" + place;
		urlWithGet = urlWithGet + "&do_remote_search=true&display=thumbnail&search_mode=advanced";
		System.out.println("  url:"+urlWithGet+"&page=(numéro de page)");
		WebGetter wg = new WebGetter();
							try {
		for(int page=1; page<=34; page++)
		{
			System.out.println("   "+page+"Page de la page");
			String source = wg.get(urlWithGet+"&page="+page);
			Parser p = new Parser(source, false);
			csv = csv + p.parse().replaceFirst("^(\r\n|\r|\n)", "");
			if(!p.has15()) break;
		}
		System.out.println("Extrémité du robot d'exploration");
		return csv;
							} catch (IOException e) {e.printStackTrace();return null;}

	}
}

La classe WebGetter ressemble à ceci: (Ajouter après NDLCrawler.java)

Classe WebGetter


/**
 *
 *Site de référence:https://www.javalife.jp/2018/04/25/java-%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%81%AE%E3%82%B5%E3%82%A4%E3%83%88%E3%81%8B%E3%82%89html%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B/
 *
 */
class WebGetter
{
	String get(String url) throws MalformedURLException, IOException
	{
		InputStream is = null; InputStreamReader isr = null; BufferedReader br = null;
							try {
		URLConnection conn = new URL(url).openConnection();
		is = conn.getInputStream();
		isr = new InputStreamReader(is);
		br = new BufferedReader(isr);

		String line, source="";
		while((line = br.readLine()) != null)
			source=source+line+"\r\n";
    	return source;
							}finally {br.close();isr.close();is.close();}
	}

}

1-1-3. Étape 4 (Créer csv à partir de la source (html) de la page de résultats)

Nous avons trouvé les règles suivantes concernant la source html des résultats de recherche dans la "Recherche de la Bibliothèque nationale de l'alimentation".

--<a href="https://iss.ndl.go.jp/books/ (ID d'un livre composé de caractères alphanumériques et de tirets) ">(chaîne de caractères 1) vient toujours immédiatement après le titre du livre .. L'inverse est vrai au moins une fois pour chaque livre. --Au moins une fois pour chaque livre, immédiatement après le titre </a> (saut de ligne) (espace blanc) + </ h3> (saut de ligne) (espace blanc) + <p> (saut de ligne) (espace blanc) + Arrive. Appelons cette chaîne 2. ―― (Nom de l'auteur) /.*(,(Nom de l'auteur) /.*)*(Chaîne de caractères 3) vient toujours immédiatement après "Chaîne de caractères 1, Titre du livre, Chaîne de caractères 2". ――Le nom de l'éditeur vient après 2 lignes de la dernière ligne de "Chaîne de caractères 1, titre du livre, chaîne de caractères 2-3", l'année de publication vient après 3 lignes et le nom de la série vient après 4 lignes. S'il manque des informations, une valeur vide sera saisie et la ligne ne sera pas ignorée.

Ce qui suit est un programme java qui crée un fichier csv avec des titres de livres organisés selon cette règle (et quelques exceptions). (Le processus de conversion de la source html en csv s'appelle Parse.)

Parser.java


package ndl;

public class Parser
{
	private boolean has15;
	private String csv;

	Parser(String source, boolean needHeader)
	{
		this.csv=needHeader?"Lien de la Bibliothèque nationale de la Diète,Titre,Auteur,Éditeur,Année,séries\n":"\n";
		String[] books = divide(source);//「<a href="https://iss.ndl.go.jp/books/Séparé par
		books = remove0(books);//Seul le début est des données sans signification, alors coupez
		has15 = books.length==15;//Par défaut, le nombre de résultats de recherche est de 15 par page.
		String link, title, publisher, year, series;
		String[] authors;
		for(String book : books)//À propos de chaque livre
		{
			book = book.replaceAll("((\r\n)|\r|\n)( |\t)*<span style=\"font-weight:normal;\">[^<]+</span>","");//Si la série est numérotée, vous pouvez l'appliquer à la «loi» en coupant cette information.
			link = getLink(book).replaceAll(",", "、");
			title = getTitle(book).replaceAll(",", "、");
			authors = getAuthors(book);
			publisher = getPublisher(book).replaceAll(",", "、");
			year = getYear(book).replaceAll(",", "、");
			series = getSeries(book).replaceAll(",", "、");//Extraire des informations détaillées
			for(String author : authors)//Convertir en csv
				csv = csv + link+","+title+","+author.replaceAll(",", "、")+","+publisher+","+year+","+series+"\n";
		}
	}

	public boolean has15(){return has15;}
	public String parse() {return csv;}

	//Des méthodes privées qui ne sont pas vraiment bonnes
	private String[] divide(String source){return source.split("<a href=\"https://iss\\.ndl\\.go\\.jp/books/", -1);}
	private String[] remove0(String[] before)
	{
		String[] after = new String[before.length-1];
		for(int i=1; i<before.length; i++)after[i-1]=before[i];
		return after;
	}
	private String getLink(String book){return "https://iss.ndl.go.jp/books/"+book.split("\"")[0];}//「"Il vous suffit de renvoyer le 0 séparé par
	private String getTitle(String book){return book.split("<|>")[1];}//「<Ou ">Il vous suffit de retourner le premier séparé par
	private String[] getAuthors(String book){return book.split("(\r\n)|\r|\n")[3].replaceFirst("( |\t)*", "").split("/([^,])+,?");}
	private String getPublisher(String book){return book.split("(\r\n)|\r|\n")[5].replaceFirst("( |\t)*", "");}
	private String getYear(String book){return book.split("(\r\n)|\r|\n")[6].replaceFirst("( |\t)*", "");}
	private String getSeries(String book){return book.split("(\r\n)|\r|\n")[7].replaceFirst("( |\t)*", "");}


}

1-1-4. Étape 4 (Contrôle du chenillard)

Conception d'une classe de robots d'exploration pour accéder à la recherche de la Bibliothèque nationale de la Diète dans les sections 1-1-2 Dans la section 1-1-3, nous avons implémenté une classe qui génère csv en fonction des informations obtenues par le robot d'exploration. Dans les sections 1-1-4, concevons une classe qui contrôle réellement le robot d'exploration à l'aide de ces classes.

En tant que contenu de contrôle, spécifiez chacun de 1925 à 2020 dans l'instruction for, spécifiez 699 comme numéro de classification, utilisez le robot d'exploration et écrivez le csv terminé dans le fichier. De plus, si vous ne connaissez pas les informations sur le nombre d'années, elles semblent être traitées comme «1900», alors considérez-le également.

Main.java


package ndl;

import java.io.*;

public class Main
{
	public static void main(String...args)
	{
		String header = "Lien de la Bibliothèque nationale de la Diète,Titre,Auteur,Éditeur,Année,séries,bibliothèque\n";
		NDLCrawler c = new NDLCrawler();
		c.setBunrui("699");
		generateCsv(c);
	}

	private static void generateCsv(NDLCrawler c)
	{
		System.out.println(1900);
		c.setYearfrom("1900");
		c.setYearto("1900");
		output(c.crawle());//Ecrire à la fin
		for(int year=1925; year<=2020; year++)
		{
			System.out.println(" "+year);
			c.setYearfrom(""+year);
			c.setYearto(""+year);
			output(c.crawle());//Ecrire à la fin
		}
	}

	private static void output(String csv)
	{
		String path = "D:\\all699.csv";//Le chemin peut être changé arbitrairement
		System.out.println("production"+csv);
							try{
		FileWriter fw = new FileWriter(path, true);//Mode d'addition à la fin avec le deuxième argument vrai
		fw.write(csv);
		fw.close();
							} catch (IOException e) {e.printStackTrace();}
	}
}

2. Résultat

L'environnement et les conditions expérimentaux sont indiqués dans le tableau 2-1.

Tableau 2-1. Environnement et conditions expérimentaux

Article Valeur
OS windows10
Logiciel Eclipse IDE for Enterprise Java Developers (4.11.0)
Fournisseurs et sources Jupiter Telecommunication Co. Ltd (210.194.32.203)
Date et heure de début du programme (heure du Japon) 17 janvier 2020 20:44:00
Heure d'arrêt du programme et période de fonctionnement, raison de l'arrêt 17 janvier 2020 21:39:44
(environ 56 minutes, fin normale)

Le fichier de sortie all699.csv (téléchargé sur github) a atteint 12 145 lignes.

De plus, après l'expérience, j'ai accédé à la recherche de la Bibliothèque nationale de la Diète avec un navigateur et j'ai regardé les informations numériques dans les résultats de la recherche dans les mêmes conditions, à savoir 12633. En raison de l'incohérence dans le nombre de livres, nous avons enquêté et constaté que le nombre total de livres donnés 1900 et 1925-2020 comme informations sur l'année de publication est de 12030. C'est un peu moins de 12145, mais on pense que cela est dû à la spécification de la méthode Parser.getAuthors qui stipule que" lorsqu'il y a plusieurs informations d'auteur, chaque ligne est attribuée séparément ".

3. Perspectives futures

Dans la recherche de la Bibliothèque nationale de l'Assemblée nationale, vous pouvez rechercher les collections de plusieurs bibliothèques locales en plus de la Bibliothèque nationale de l'Assemblée nationale. Je suis intéressé à l'utiliser pour l'appliquer à la recherche qui classe les «livres qui sont placés partout» et les «livres qui ne le sont pas», alors j'aimerais essayer ceci.

Recommended Posts

Créer une base de données de tous les livres qui ont circulé au Japon au siècle dernier
Créons une application TODO en Java 5 Changer l'affichage de TODO
[Android] Développer un service permettant aux étudiants universitaires de vérifier l'état de fonctionnement des bus circulant dans l'université.
Exemple de programme qui renvoie la valeur de hachage d'un fichier en Java
Création d'un exemple de programme en utilisant le problème d'un spécialiste des bases de données dans DDD Improvement 2
Je ne peux pas importer le package qui aurait dû être installé par conda sur Anaconda
Création d'un exemple de programme en utilisant le problème d'un spécialiste des bases de données avec DDD Improvement 1
Code pour supprimer tous les fichiers du préfixe spécifié dans AWS S3 (Java)
Mesurer la taille d'un dossier avec Java
Supprimer tous les enregistrements d'une table dans une base de données MySQL