myapp6.js 20 KB

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