如何使用 Perl 将 MARC 文件中的 ISBN 替换为 Google 图书 ID?
-
13-09-2019 - |
题
我有一个包含一些书籍数据的文件 机读目录 格式,其中一些行是 ISBN。我想将这些行替换为该 ISBN 的 Google 图书 ID(如果存在)。这是到目前为止的代码,最终删除了这些行:
perl -pe "s#ISBN(.*)#$(wget --output-document=- --quiet --user-agent=Mozilla/5.0 \"http://books.google.com/books?jscmd=viewapi&bibkeys=\1\")#mg" < 5-${file} > 6-${file}
附:谷歌对自动化工具的使用有点模糊:这 图书数据API 推荐了像curl/wget这样的工具,但是没有说明如何避免使用此类工具时被阻止。我也很确定我在服务条款中看到了一个条款,说用户不能发送自动查询,但我找不到它了。这是 讨论过 在他们的论坛中。
解决方案
我觉得OP是在正确的轨道上,并可以使用一个班轮这一点,并且只需要替换为正确的Perl的语法部分的bash风格的语法。我认为这会工作(换行的可读性加):
perl -pe 's#ISBN(\w+)#qx(wget --output-document=-
--quiet --user-agent=Mozilla/5.0
"http://books.google.com/books\\?jscmd=viewapi\\&bibkeys=$1")#ge' \
< 5-${file} > 6-${file}
您必须逃走。(编辑:双重转义似乎工作)在URL中$
或&
字符
其他提示
您最终不得不对用户代理撒谎的原因是您违反了 Google 的 TOS:不要那样做。
相反,使用 Google 图书搜索 API.
由于我对以下模块缺乏熟悉,下面的代码略有阻碍 XML::原子, 数据馈送, WWW::打开搜索. 。然而,它应该提供一个良好的起点。
#!/usr/bin/perl
use strict;
use warnings;
use Business::ISBN qw( valid_isbn_checksum );
use LWP::Simple;
use XML::Simple;
while ( <> ) {
s/ISBN:([0-9]+)/'Google Books ID:' . get_google_id_for_isbn($1)/ge;
print;
}
use Carp;
sub make_google_books_query {
sprintf 'http://books.google.com/books/feeds/volumes?q=isbn:%s', $_[0];
}
sub get_google_id_for_isbn {
my ($isbn) = @_;
my $google_id = eval {
defined(valid_isbn_checksum $isbn)
or croak "Invalid ISBN: $isbn";
my $query = make_google_books_query($isbn);
my $xml = get $query;
defined($xml)
or croak "No response to <$query>";
my $data = XMLin($xml, ForceArray => 1);
my @ids = @{ $data->{entry}[0]{'dc:identifier'} };
unless ("ISBN:$isbn" eq $ids[1]
or "ISBN:$isbn" eq $ids[2] ) {
croak "Invalid search results: '@ids'";
}
$ids[0];
};
defined($google_id) ? $google_id : '';
}
给定一个文本文件 t.txt
包含:
ISBN:0060930314 ISBN:9780596520106
它输出:
Google Books ID:ioXFqlzsmK8C Google Books ID:lNVHi3TunxsC
不隶属于 StackOverflow