如何使用 Perl 将 MARC 文件中的 ISBN 替换为 Google 图书 ID?

发布于 2024-08-09 18:22:56 字数 747 浏览 10 评论 0原文

我有一个文件,其中包含 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-${文件}> 6-${file}

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

I've got a file with some book data in MARC format, of which some lines are ISBNs. I'd like to replace these lines with the Google Books ID of that ISBN, if it exists. Here's the code so far, which just ends up removing the lines:

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 are a bit fuzzy on the use of automated tools: The Books Data API recommends tools like curl / wget, but there are no instructions on how to avoid being blocked when using such tools. I'm also pretty sure I saw a clause in a ToS saying users can't send automated queries, but I can't find it again. This is discussed in their forum.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

空气里的味道 2024-08-16 18:22:56

您最终不得不对用户代理撒谎的原因是因为您违反了 Google 的 TOS:不要这样做。

请改用 Google 图书搜索 API

由于我对 XML::Atom、Data::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 包含:

ISBN:0060930314
ISBN:9780596520106

它输出:

Google Books ID:ioXFqlzsmK8C
Google Books ID:lNVHi3TunxsC

The reason you end up having to lie about the user agent is because you are violating Google's TOS: Don't do that.

Instead, use the Google Book Search API.

The code below is slightly hampered by my lack of familiarity with modules such as XML::Atom, Data::Feed, WWW::OpenSearch. However, it should provide a good starting point.

#!/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 : '';
}

Given a text file t.txt containing:

ISBN:0060930314
ISBN:9780596520106

it outputs:

Google Books ID:ioXFqlzsmK8C
Google Books ID:lNVHi3TunxsC
疾风者 2024-08-16 18:22:56

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

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

I think the OP is on the right track and could use a one-liner for this, and just needs to replace some bash-style syntax with the correct Perl syntax. I think this would work (newlines added for readability):

    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}

You have to escape (edit: double escaping seems to work) the $ or & characters in the url.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文