myapp5.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. // programme de scraping des données de Maine.edu
  2. var jsdom = require("jsdom");
  3. const {
  4. JSDOM
  5. } = jsdom;
  6. // librairie de gestion des répertoires et fichiers
  7. const fs = require("fs");
  8. const path = require("path");
  9. // librairie de gestion des arguments de la ligne de commande
  10. var argv = require("optimist").argv;
  11. // librairie base de données sqlite
  12. const sq = require("better-sqlite3");
  13. // librairie de traitement du pinyin
  14. const pinyinizer = require('pinyinizer');
  15. // librairie de gestion des fichiers xml
  16. const builder = require('xmlbuilder');
  17. // librairie de gestion du hanzi
  18. const opencc = require('node-opencc');
  19. // temporaire
  20. var prompt = require('prompt');
  21. prompt.start();
  22. //
  23. // données de stockage
  24. var fichierXml = "MaineEdu-datas.xml";
  25. var fichierJson = "MaineEdu-datas.json";
  26. var baseDeDonnées = "MaineEdu-datas.db";
  27. var fichierCSV = "MaineEdu-datas.csv";
  28. // données en mémoire
  29. // le fichier complet en mémoire
  30. var maineeduObj = {
  31. "maineedu": []
  32. };
  33. var phraseObj = {
  34. "phrase": {
  35. "topic": "",
  36. "hanzi": {
  37. "simplified": "",
  38. "traditional": ""
  39. },
  40. "pinyin": "",
  41. "translations": [],
  42. "recordings": []
  43. }
  44. }
  45. // fichier des locuteurs
  46. var locuteurs = [];
  47. // un locuteur
  48. var locuteur = {
  49. "nom": "",
  50. "langue": ""
  51. }
  52. var tab = "\t";
  53. var endLine = "\n";
  54. // fin des données en mémoire
  55. // données calculées
  56. var repertoireInitial = "";
  57. var repertoireCourant = "";
  58. var fichierCourant = "";
  59. // fin des données calculées
  60. // fonctions utilitaires
  61. // reset d'un enregistrement
  62. function reset(p) {
  63. phraseObj = {
  64. "phrase": {
  65. "topic": "",
  66. "hanzi": {
  67. "simplified": "",
  68. "traditional": ""
  69. },
  70. "pinyin": "",
  71. "translations": [],
  72. "recordings": []
  73. }
  74. }
  75. }
  76. // fin du reste d'un enregistrement
  77. // détermination du répertoire de travail et mise à jour des variables
  78. repertoireInitial = path.resolve(path.join("./",argv._[0]));
  79. // DEBUG
  80. // console.log("réperoire initial:", repertoireInitial); // OK
  81. fichierXml = path.join(repertoireInitial,"MaineEdu-datas.xml");
  82. fichierJson = path.join(repertoireInitial,"MaineEdu-datas.json");
  83. baseDeDonnées = path.join(repertoireInitial,"MaineEdu-datas.db");
  84. fichierCSV = path.join(repertoireInitial,"MaineEdu-datas.csv");
  85. // DEBUG
  86. // console.log(fichierXml," ",fichierJson, " ",baseDeDonnées, " ",fichierCSV); // OK
  87. // fin de la détermination du répertoire de travail
  88. // fin des fonctions utilitaires
  89. // fonctions de traitement des fichiers html, c. douying et douzhong
  90. // traitement des fichiers c
  91. function traiteFichierC(formalfile) {
  92. // fonction de scraping des fichiers c*.html
  93. var html = fs.readFileSync(formalfile, "UTF-8");
  94. dom = new JSDOM(html);
  95. var $ = require('jquery')(dom.window);
  96. // on traite le topic
  97. var $header = $.find("#header H1");
  98. // DEBUG console.log("Le header est: " + $($header).text());
  99. var topic = $($header).text();
  100. // on traite les "rows"
  101. $z = dom.window.$(".row ").each(function(index, element) {
  102. // le topic
  103. phraseObj.phrase.topic = topic;
  104. var ligneCSV = "";
  105. var csv1 = "";
  106. var csv2 = "";
  107. //traitement des données textuelles : Hanzi, Pinyin et traduction en anglais
  108. //c'est la seule partie qui change entre les différents fichiers.
  109. // on retrouve le texte en chinois
  110. // DEBUG console.log("index: " + index + " texte en hanzi: " + $(element).find("p .chinese").text());
  111. var hanzi = $(element).find("p .chinese").text();
  112. var traditional = opencc.simplifiedToTraditional(hanzi);
  113. phraseObj.phrase.hanzi.simplified = hanzi;
  114. phraseObj.phrase.hanzi.traditional = traditional;
  115. csv1 = hanzi + tab + traditional + tab;
  116. // on retrouve le texte en anglais et pinyin
  117. // DEBUG console.log("texte en pinyin et traduction en anglais");
  118. // l'anglais
  119. var anglais = $(element).find(".indented img:first").attr("title");
  120. // DEBUG console.log(anglais);
  121. var translationObj = {
  122. "translation": {}
  123. };
  124. translationObj.translation.langue = "en";
  125. translationObj.translation.texte = anglais;
  126. phraseObj.phrase.translations.push(translationObj);
  127. // le pinyin que l'on transforme d'une version avec chiffres à une version avec accents
  128. var pinyin = $(element).find(".indented img:nth-child(2)").attr("title");
  129. pinyin = pinyin.toLowerCase();
  130. // on va tester ça ...
  131. try {
  132. phraseObj.phrase.pinyin = pinyinizer.pinyinize(pinyin);
  133. }
  134. catch(err) {
  135. console.log("Erreur: " + pinyin);
  136. phraseObj.phrase.pinyin = pinyin;
  137. }
  138. // modif pour court-circuiter pinyinise
  139. //phraseObj.phrase.pinyin = pinyin;
  140. csv1 = csv1 + phraseObj.phrase.pinyin + tab + anglais + tab;
  141. // DEBUG $(element).find(".indented img").each(function(index, letexte) {
  142. // console.log("---->" + $(this).attr("title"));
  143. // });
  144. // // traitement des données audio en anglais et en chinois
  145. // // on retrouve les enregistrements
  146. var $t = $(element).find(".speech_samples:first");
  147. // // prononctation en chinois
  148. // DEBUG console.log("--> Prononciation en chinois");
  149. $t.find("tr:first td a:nth-child(2)").each(function(index, audio) {
  150. // DEBUG console.log("--> " + index + " " + $(this).text() + " " + $(this).attr("href"));
  151. var recordingObject = {
  152. "recording": {}
  153. };
  154. recordingObject.recording.langue = "zh";
  155. recordingObject.recording.locuteur = $(this).text();
  156. recordingObject.recording.audio = $(this).attr("href");
  157. // transformation de l'url du fichier son: ../../Language/Sound19b/19103sjx.wav => [sound:MaineEdu-19103sjx.mp3]
  158. var xx = recordingObject.recording.audio;
  159. xx = path.basename(xx,".wav");
  160. xx = "[sound:MaineEdu-" + xx + ".mp3]";
  161. recordingObject.recording.audio = xx;
  162. // fin de transformation
  163. phraseObj.phrase.recordings.push(recordingObject);
  164. // on crée la ligne csv à écrire dans le fichier
  165. csv2 = recordingObject.recording.locuteur + tab + recordingObject.recording.audio;
  166. ligneCSV = csv1 + csv2 + tab + topic + tab + "MaineEdu" + endLine;
  167. csv.write(ligneCSV);
  168. });
  169. // prononciation en anglais
  170. // DEBUG console.log("--> Prononciation en anglais");
  171. $t.find("tr:nth-child(2) td a:nth-child(2)").each(function(index, audio) {
  172. // DEBUG console.log("--> " + index + " " + $(this).text() + " " + $(this).attr("href"));
  173. var recordingObject = {
  174. "recording": {}
  175. };
  176. recordingObject.recording.langue = "en";
  177. recordingObject.recording.locuteur = $(this).text();
  178. recordingObject.recording.audio = $(this).attr("href");
  179. phraseObj.phrase.recordings.push(recordingObject);
  180. });
  181. // DEBUG console.log(JSON.stringify(phraseObj));
  182. maineeduObj.maineedu.push(phraseObj);
  183. var ele = feed.ele(phraseObj);
  184. reset(phraseObj);
  185. });
  186. }
  187. // fin du traitement des fichiers c
  188. // traitement des fichiers douying
  189. function traiteFichierDouying(formalfile) {
  190. var html = fs.readFileSync(formalfile, "UTF-8");
  191. dom = new JSDOM(html);
  192. var $ = require('jquery')(dom.window);
  193. // on traite le topic
  194. var $header = $.find("#header H1");
  195. // DEBUG console.log("Le header est: " + $($header).text());
  196. var topic = $($header).text();
  197. // on traite les "rows"
  198. $z = dom.window.$(".row ").each(function(index, element) {
  199. // le topic
  200. phraseObj.phrase.topic = topic;
  201. var ligneCSV = "";
  202. var csv1 = "";
  203. var csv2 = "";
  204. //traitement des données textuelles : Hanzi, Pinyin et traduction en anglais
  205. //c'est la seule partie qui change entre les différents fichiers.
  206. // on retrouve le texte en chinois
  207. // DEBUG console.log("index: " + index + " texte en hanzi: " + $(element).find("p .chinese").text());
  208. var hanzi = $(element).find("p .chinese").text();
  209. var traditional = opencc.simplifiedToTraditional(hanzi);
  210. phraseObj.phrase.hanzi.simplified = hanzi;
  211. phraseObj.phrase.hanzi.traditional = traditional;
  212. csv1 = hanzi + tab + traditional + tab;
  213. // on retrouve le texte en anglais et pinyin
  214. // DEBUG console.log("texte en pinyin et traduction en anglais");
  215. // l'anglais
  216. var anglais = $(element).find("p .english").text();
  217. // DEBUG console.log(anglais);
  218. var translationObj = {
  219. "translation": {}
  220. };
  221. translationObj.translation.langue = "en";
  222. translationObj.translation.texte = anglais;
  223. phraseObj.phrase.translations.push(translationObj);
  224. // le pinyin que l'on transforme d'une version avec chiffres à une version avec accents
  225. var pinyin = $(element).find("p .pinyin").text();
  226. pinyin = pinyin.toLowerCase();
  227. // phraseObj.phrase.pinyin = pinyinizer.pinyinize(pinyin);
  228. // on va tester ça ...
  229. try {
  230. phraseObj.phrase.pinyin = pinyinizer.pinyinize(pinyin);
  231. }
  232. catch(err) {
  233. console.log("Erreur: " + pinyin);
  234. phraseObj.phrase.pinyin = pinyin;
  235. }
  236. csv1 = csv1 + phraseObj.phrase.pinyin + tab + anglais + tab;
  237. // DEBUG $(element).find(".indented img").each(function(index, letexte) {
  238. // console.log("---->" + $(this).attr("title"));
  239. // });
  240. // // traitement des données audio en anglais et en chinois
  241. // // on retrouve les enregistrements
  242. var $t = $(element).find(".speech_samples:first");
  243. // // prononctation en chinois
  244. // DEBUG console.log("--> Prononciation en chinois");
  245. $t.find("tr:first td a:nth-child(2)").each(function(index, audio) {
  246. // DEBUG console.log("--> " + index + " " + $(this).text() + " " + $(this).attr("href"));
  247. var recordingObject = {
  248. "recording": {}
  249. };
  250. recordingObject.recording.langue = "zh";
  251. recordingObject.recording.locuteur = $(this).text();
  252. recordingObject.recording.audio = $(this).attr("href");
  253. phraseObj.phrase.recordings.push(recordingObject);
  254. // on crée la ligne csv à écrire dans le fichier
  255. csv2 = recordingObject.recording.locuteur + tab + recordingObject.recording.audio;
  256. ligneCSV = csv1 + csv2 + tab + topic + tab + "MaineEdu" + endLine;
  257. csv.write(ligneCSV);
  258. });
  259. // prononciation en anglais
  260. // DEBUG console.log("--> Prononciation en anglais");
  261. $t.find("tr:nth-child(2) td a:nth-child(2)").each(function(index, audio) {
  262. // DEBUG console.log("--> " + index + " " + $(this).text() + " " + $(this).attr("href"));
  263. var recordingObject = {
  264. "recording": {}
  265. };
  266. recordingObject.recording.langue = "en";
  267. recordingObject.recording.locuteur = $(this).text();
  268. recordingObject.recording.audio = $(this).attr("href");
  269. phraseObj.phrase.recordings.push(recordingObject);
  270. });
  271. // DEBUG console.log(JSON.stringify(phraseObj));
  272. maineeduObj.maineedu.push(phraseObj);
  273. var ele = feed.ele(phraseObj);
  274. reset(phraseObj);
  275. });
  276. }
  277. // fin du traitement des fichiers douying
  278. // traitement de fichiers douzhong
  279. function traiteFichierDouzhong(formalfile) {
  280. var html = fs.readFileSync(formalfile, "UTF-8");
  281. dom = new JSDOM(html);
  282. var $ = require('jquery')(dom.window);
  283. // on traite les ul
  284. var $z = dom.window.$("ul input").parent().each(function(index, element) {
  285. //DEBUG console.log("numéro élément: " + index);
  286. // le topic
  287. phraseObj.phrase.topic = topic;
  288. var ligneCSV = "";
  289. var csv1 = "";
  290. var csv2 = "";
  291. //DEBUG console.log("*****************");
  292. // le hanzi
  293. var hanzi = $(element).find("font:first").text();
  294. var traditional = opencc.simplifiedToTraditional(hanzi);
  295. phraseObj.phrase.hanzi.simplified = hanzi;
  296. phraseObj.phrase.hanzi.traditional = traditional;
  297. csv1 = hanzi + tab + traditional + tab;
  298. // on retrouve le texte en anglais et pinyin et les explications
  299. var secondul = $(element).find("ul:first");
  300. var jumeaux = $(secondul).find("font").siblings();
  301. var pinyin = $(jumeaux).first().text();
  302. var anglais = $(jumeaux).next("font:first").text();
  303. var explications = $(secondul).find("ul").text().trim();
  304. // l'anglais
  305. var translationObj = {
  306. "translation": {}
  307. };
  308. translationObj.translation.langue = "en";
  309. translationObj.translation.texte = anglais;
  310. phraseObj.phrase.translations.push(translationObj);
  311. // le pinyin
  312. // le pinyin que l'on transforme d'une version avec chiffres à une version avec accents
  313. pinyin = pinyin.toLowerCase();
  314. try {
  315. phraseObj.phrase.pinyin = pinyinizer.pinyinize(pinyin);
  316. }
  317. catch(err) {
  318. console.log("Erreur: " + pinyin);
  319. phraseObj.phrase.pinyin = pinyin;
  320. }
  321. // on continue à construire la ligne csv
  322. csv1 = csv1 + phraseObj.phrase.pinyin + tab + anglais + tab + explications + tab;
  323. // DEBUG console.log(csv1);
  324. // traitement des enregistrements ... chinois et anglais
  325. // le chinois :) et l'anglais ...
  326. var $x = $(secondul).find("a[href]").each(function(index, element) {
  327. var $b = $(element).find("img[SRC='../tingsmgl.jpg']");
  328. if ($b.length == 1) {
  329. // DEBUGconsole.log(index, $b);
  330. // DEBUGconsole.log($(element).attr("href"));
  331. // DEBUGconsole.log($(element).text());
  332. var recordingObject = {
  333. "recording": {}
  334. };
  335. recordingObject.recording.langue = "zh";
  336. recordingObject.recording.locuteur = $(element).text().trim();
  337. recordingObject.recording.audio = $(element).attr("href");
  338. phraseObj.phrase.recordings.push(recordingObject);
  339. // on crée la ligne csv à écrire dans le fichier
  340. csv2 = recordingObject.recording.locuteur + tab + recordingObject.recording.audio;
  341. ligneCSV = csv1 + csv2 + tab + topic + tab + "MaineEdu" + endLine;
  342. csv.write(ligneCSV);
  343. maineeduObj.maineedu.push(phraseObj);
  344. var ele = feed.ele(phraseObj);
  345. reset(phraseObj);
  346. }
  347. })
  348. }
  349. );
  350. }
  351. // fin du traitement des fichiers douzhong
  352. // fin du traitement des fichiers html
  353. // on crée le fichier xml
  354. var feed = builder.create('maineedu', {
  355. version: '1.0',
  356. encoding: 'UTF-8',
  357. standalone: true
  358. });
  359. // on crée le fichier csv
  360. var csv = fs.createWriteStream(fichierCSV);
  361. // on parcours l'arborescence
  362. var repertoires = fs.readdirSync(repertoireInitial);
  363. repertoires.forEach(function(repertoire) {
  364. // gestion des répertoires
  365. repertoire = path.join(repertoireInitial,repertoire);
  366. // DEBUG console.log("%s", repertoire); // OK
  367. if (fs.statSync(repertoire).isDirectory()) {
  368. // On traite chaque répertoire
  369. // DEBUG console.log("%s", repertoire); // OK
  370. repertoireCourant = path.basename(repertoire);
  371. // DEBUG console.log(repertoireCourant); // OK
  372. // Recherche des fichiers c*.html
  373. ffiles = fs.readdirSync(repertoire);
  374. var fichiers = ffiles.filter((ffile) => ffile[0] == "c" );
  375. // DEBUG console.log( repertoireCourant, " ", fichiers);
  376. if (fichiers == "") {
  377. // console.log("pas de fichiers c");
  378. fichiers = ffiles.filter((ffile) => ffile == "douying.html" );
  379. // DEBUG console.log( repertoireCourant, " ", fichiers);
  380. if (fichiers == "") {
  381. // console.log("pas de fichiers douying");
  382. fichiers = ffiles.filter((ffile) => ffile == "douzhong.html" );
  383. // DEBUG console.log( repertoireCourant, " ", fichiers);
  384. if (fichiers != "") {
  385. // traitement des douzhong
  386. fichierCourant = path.join(repertoireInitial, repertoireCourant, "douzhong.html");
  387. console.log(fichierCourant);
  388. traiteFichierDouying(fichierCourant);
  389. }
  390. } else {
  391. // traitement des douying
  392. fichierCourant = path.join(repertoireInitial, repertoireCourant,"douying.html" );
  393. console.log(fichierCourant);
  394. traiteFichierDouzhong(fichierCourant);
  395. }
  396. } else {
  397. // traitement des fichiers c
  398. fichiers.forEach(function(fffile) {
  399. fichierCourant = path.join(repertoireInitial, repertoireCourant, fffile);
  400. // DEBUG
  401. console.log(fichierCourant);
  402. traiteFichierC(fichierCourant);
  403. });
  404. }
  405. };
  406. });
  407. // fin du parcours de l'arborescence
  408. // on ferme le fichier CSV
  409. csv.end();
  410. // on écrit le fichier xml
  411. fs.writeFileSync(fichierXml, feed.end({
  412. pretty: true
  413. }));
  414. // on écrit le fichier Json
  415. fs.writeFileSync(fichierJson, JSON.stringify(maineeduObj), "UTF-8");
  416. // DEBUG console.log(JSON.stringify(maineeduObj));