1

我有一个文件,其中包含一些MARC格式的图书数据,其中一些行是 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}

PS:Google 对自动化工具的使用有点模糊:Books Data API推荐使用 curl / wget 之类的工具,但没有说明如何避免在使用此类工具时被屏蔽。我也很确定我在 ToS 中看到一个子句说用户不能发送自动查询,但我再也找不到它了。这是在他们的论坛中讨论的。

4

2 回答 2

5

你最终不得不对用户代理撒谎的原因是因为你违反了谷歌的服务条款:不要那样做。

相反,请使用Google Book Search API

由于我对XML::AtomData::FeedWWW::OpenSearch等模块不熟悉,下面的代码略有阻碍。但是,它应该提供一个很好的起点。

#!/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

国际标准书号:0060930314
国际标准书号:9780596520106

它输出:

Google 图书 ID:ioXFqlzsmK8C
Google 图书 ID:lNVHi3TunxsC
于 2009-11-03T17:09:07.430 回答
1

我认为 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}

您必须转义(编辑:双重转义似乎有效)网址中的$or&字符。

于 2009-11-03T15:59:15.220 回答