Я решил эту проблему, написав небольшую программу (называемую extract.js) в node.js для очистки текста. Я использовал эту страницу, чтобы помочь мне: http://blog.miguelgrinberg.com/post/easy-web-scraping-with-nodejs
Каждая html-страница содержит несколько страниц книги. Поэтому, если мы увеличим параметр страницы в URL-адресе только на 1, то мы будем отбирать дубликаты страниц книги, если не будем соблюдать осторожность (это была часть, на которой я особенно застрял). Я справился с этим с помощью селектора jquery, чтобы выбрать только отдельную страницу книги, указанную в URL, и игнорировать другие страницы книги, присутствующие в html. Таким образом, я мог быстро создать текстовый файл, используя программу для работы с электронными таблицами с URL-адресами для каждой отдельной страницы по порядку (потому что приращение составляет только 1).
Пока я успешно соскоблил первые два тома, еще пять осталось! Код приведен ниже, он может послужить полезной отправной точкой для очистки других книг Google.
// Usage: node extract.js input output
// where input (mandatory) is the text file containing your list of urls
// and output (optional) is the directory where the output files will be saved
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
// Read the command line parameters
var input = process.argv[2];
var output = process.argv[3];
if (!input) {
console.log("Missing input parameter");
return;
}
// Read the url input file, each url is on a new line
var urls = fs.readFileSync(input).toString().split('\n');
// Check for non urls and remove
for (var i = 0; i < urls.length; i++) {
if (urls[i].slice(0, 4) != 'http') {
urls.splice(i, 1);
}
}
// Iterate through the urls
for (var i = 0; i < urls.length; i++) {
var url = urls[i];
// request function is asynchronous, hence requirement for self-executing function
// Cannot guarantee the execution order of the callback for each url, therefore save results to separate files
request(url, ( function(url) {
return function(err, resp, body) {
if (err)
throw err;
// Extract the pg parameter (book page) from the url
// We will use this to only extract the text from this book page
// because a retrieved html page contains multiple book pages
var pg = url.slice(url.indexOf('pg=') + 3, url.indexOf('&output=text'));
//
// Define the filename
//
var number = pg.slice(2, pg.length);
var zeroes = 4 - number.length;
// Insert leading zeroes
for (var j = 0; j < zeroes; j++) {
number = '0' + number;
}
var filename = pg.slice(0, 2) + number + '.txt';
// Add path to filename
if (output) {
if (!fs.existsSync(output))
fs.mkdirSync(output);
filename = output + '/' + filename;
}
// Delete the file if it already exists
if (fs.existsSync(filename))
fs.unlinkSync(filename);
// Make the DOM available to jquery
$ = cheerio.load(body);
// Select the book page
// Pages are contained within 'div' elements (where class='flow'),
// each of which contains an 'a' element where id is equal to the page
// Use ^ to match pages because sometimes page ids can have a trailing hyphen and extra characters
var page = $('div.flow:has(a[id=' + pg + ']), div.flow:has(a[id^=' + pg + '-])');
//
// Extract and save the text of the book page to the file
//
var hasText = false;
// Text is in 'gtxt_body', 'gtxt_column' and 'gtxt_footnote'
page.find('div.gtxt_body, div.gtxt_column, div.gtxt_footnote').each(function() {
this.find('p.gtxt_body, p.gtxt_column, p.gtxt_footnote').each(function() {
hasText = true;
fs.appendFileSync(filename, this.text());
fs.appendFileSync(filename, '\n\n');
});
});
// Log progress
if (hasText) {
console.log("Retrieved and saved page: " + pg);
}
else {
console.log("Skipping page: " + pg);
}
}
} )(url));
}