Web-Scraping / Crawlen eines bestimmten Google-Buchs

2423
user2661243

Für meine Arbeit muss ich den Text aus einem großen Buch in Google Books herauskratzen. Das fragliche Buch ist ein sehr altes Buch und nicht urheberrechtlich geschützt. Das Buch ist ein Gazetteer der Welt. Wir werden den Text in eine Datenbank schreiben, also brauchen wir den Rohtext anstelle des PDFs.

Ich habe bereits viel Zeit damit verbracht, die Werkzeuge und Techniken zu erforschen, mit denen diese Aufgabe erledigt werden kann. Ich fühle mich überfordert und weiß nicht, wo ich anfangen soll oder welche Methode die beste / einfachste ist. Ich möchte nicht mehr Zeit mit einer Sackgasse verbringen.

Das Problem kann in zwei Teile aufgeteilt werden:

  1. Die Seiten kriechen
  2. Daten herunterladen

Es ist wirklich Teil (1), an dem ich am meisten festhalte. Sobald ich die Daten habe (auch wenn es nur die rohen HTML-Seiten sind), bin ich sicher, dass ich einen Parser verwenden könnte, um das zu extrahieren, was ich will.

Die Navigation der Seiten erfolgt durch Klicken auf Weiter oder einen Pfeil. Das Seiteninkrement ist nicht immer konsistent und kann variieren, da einige Seiten eingebettete Bilder enthalten. Daher kann ich die nächste URL nicht unbedingt vorhersagen. Die anfängliche URL für Band 1 des Buches lautet:

http://books.google.co.uk/books?id=grENAAAAQAAJ&pg=PR5&output=text

Ich kann in Java und JavaScript programmieren und habe Grundkenntnisse in Python. Ich habe node.js und scrapy neben vielen anderen Dingen betrachtet. Ich habe wget ausprobiert, erhalte jedoch einen 401 nicht autorisierten Zugriffsfehler. Ich habe auch iRobot, GreaseMonkey und FoxySpider ausprobiert.

2

2 Antworten auf die Frage

1
Jan Doggen

Wenn ich eine Google-Suche durchführe download "Gazetteer of the World" dictionary of geographic knowledge, sehe ich, dass sie zB in PDF verfügbar ist, und dann kann etwas wie PDF2Word verwendet werden, um den Text zu extrahieren.

Es sei denn, das PDF enthält alle Bilder ;-) Dann könnten Sie versuchen, mit pdf2jpg zu extrahieren und die Bilddateien mit einem OCR-Programm zu füttern.

Sie können sie auch kaufen (Amazon hat mehrere Treffer), die Seiten ausschneiden und durch einen Scanner mit automatischem Vorschub und OCR ziehen.

Da dies ein einmaliger Aufwand ist, wäre die Programmierung mein allerletzter Ausweg.

Dies kann hilfreich sein, wenn Sie zunächst ein Inventar des Formats erstellen, in dem Sie die (6?) Volumina erwerben können, und eine Schätzung der Kosten und des Arbeitsaufwands dieser Formate vornehmen wird.

Danke für die Vorschläge. Ich habe PDF2Word ausprobiert, aber es hat nicht funktioniert, ich glaube, weil der Text in der Datei ein Bild ist. Ich habe über die OCR-Datei der PDF-Datei nachgedacht, aber die Auflösung ist nicht sehr hoch und ich denke, es werden Probleme damit verbunden sein. user2661243 vor 10 Jahren 0
1
user2661243

Ich habe dieses Problem gelöst, indem ich ein kleines Programm (namens extract.js) in node.js geschrieben habe, um den Text zu kratzen. Ich habe diese Seite verwendet, um mir zu helfen: http://blog.miguelgrinberg.com/post/easy-web-scraping-with-nodejs

Jede HTML-Seite enthält mehrere Buchseiten. Wenn wir also den Seitenparameter in der URL nur um 1 erhöhen, würden wir doppelte Buchseiten auskratzen, wenn wir nicht aufpassen (dies war der Teil, auf den ich besonders geklebt habe). Ich bin damit umgekommen, indem ich mit einem Jquery-Selector nur die in der URL angegebene einzelne Buchseite auswähle und die anderen in der HTML-Datei vorhandenen Buchseiten ignoriere. Auf diese Weise konnte ich schnell eine Textdatei mit einem Tabellenkalkulationsprogramm erstellen, wobei die URLs für jede einzelne Seite in der Reihenfolge angegeben wurden (da das Inkrement nur 1 beträgt).

Bis jetzt habe ich die ersten beiden Bände erfolgreich geschafft, fünf weitere noch! Der Code ist unten angegeben. Er kann als nützlicher Einstieg für das Scraping anderer Google-Bücher dienen.

// 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)); } 
Möglicherweise muss ich den Code so ändern, dass er nicht die Reihenfolge von gtxt_body usw. annimmt. Ich bin gerade auf eine Seite gestoßen, auf der gtxt_footnote über gtxt_column steht. user2661243 vor 10 Jahren 0