Package: eprints2archives
eprints2archivesA program that can obtain records from an EPrints server and send them to public web archiving services such as thethe Wayback Machine at the Internet Archiveand others.Table of contentsIntroductionInstallationUsageKnown issues and limitationsRelationships to other similar toolsGetting helpContributingLicenseAuthors and historyAcknowledgmentsIntroductioneprints2archivesis a self-contained program to archive the web pages of an EPrints server in public web archiving sites such as theInternet Archive.  It contacts an EPrints server, obtains the list of documents it serves (optionally filtered based on such things as modification date), determines the document URLs, extracts additional URLs by scraping pages under the/viewsection of the public site, and finally, sends the collected URLs to web archives.  Use-cases include archiving an server content ahead of migration to another system, and preserving contents in independent third-party archives.The program is written in Python 3 and works over a network using an EPrints server's REST API and normal HTTP.eprints2archivescan work with EPrints servers that require logins as well as those that allow anonymous access.  It uses parallel threads by default, transparently handles rate limits, and robustly deals with network errors.Click to run asciinema screencast.InstallationThe instructions below assume you have a Python interpreter version 3.6 or higher installed on your computer; if that's not the case, please first install Python and familiarize yourself with running Python programs on your system. If you are unsure of which version of Python you have, you can find out by running the following command in a terminal and inspecting the results:# Note: on Windows, you may have to use "python" instead of "python3"python3--versionNote: if you are using macOS Catalina (10.15) or later and have never runpython3, then the first time you do, macOS will ask you if you want to install the macOS command-line developer tools.  Go ahead and do so, as this is the easiest way to get a recent-enough Python 3 on those systems.Approach 1: using the standalone executablesBeginning with version 1.3.2, runnable self-contained single-file executables are available for select operating system and Python version combinations – to use them, youonlyneed a Python 3 interpreter and a copy ofeprints2archives, butdo notneed to runpip installor other steps. Please click on the relevant heading below to learn more.macOSVisit theeprints2archives releases pageand look for the ZIP files with names such as (e.g.)eprints2archives-1.3.3-macos-python3.8.zip. Then:Download the one matching your version of PythonUnzip the file (if your browser did not automatically unzip it for you)Open the folder thus created (it will have a name likeeprints2archives-1.3.3-macos-python3.8)Look inside foreprints2archivesand move it to a location where you put other command-line programs (e.g.,/usr/local/bin)LinuxVisit theeprints2archives releases pageand look for the ZIP files with names such as (e.g.)eprints2archives-1.3.3-linux-python3.8.zip. Then:Download the one matching your version of PythonUnzip the file (if your browser did not automatically unzip it for you)Open the folder thus created (it will have a name likeeprints2archives-1.3.3-linux-python3.8)Look inside foreprints2archivesand move it to a location where you put other command-line programs (e.g.,/usr/local/bin)WindowsStandalone executables for Windows are not available at this time. If you are running Windows, please use one of the other methods described below.Approach 2: usingpipOnLinux,macOS, andWindowsoperating systems, you should be able to install or upgradeeprints2archiveswithpip.  To installeprints2archivesfrom thePython package repository (PyPI), run the following command:python3 -m pip install eprints2archives --upgradeApproach 3: usinggit cloneAs an alternative to getting it fromPyPI, you can usepipto install or upgradeeprints2archivesdirectly from GitHub, like this:python3-mpipinstallgit+https://github.com/caltechlibrary/eprints2archives.git--upgradeUsageRunningeprints2archivesfrom a terminal shell then should be as simple as running any other shell command on your system:eprints2archives-hIf that fails for some reason, you should be able to runeprints2archivesfrom anywhere using the normal approach for running Python modules:python3-meprints2archives-hOn Windows, Python 3 is usually installed as justpythoninstead ofpython3, andeprints2archivesfollows the Windows convention of using/as the option prefix instead of a dash (-).  So, instead of the above, you would typepython-meprints2archives/hSpecifying the EPrints serverTheeprints2archivesprogram contacts the EPrints server whose web address is given as the value to the option-a(or/aon Windows).  A typical EPrints server REST API will have a URL of the formhttps://server.institution.edu/rest, but you can give it justhttps://server.institution.eduandeprints2archiveswill add the/restpart if it is missing.  Note thata value for-ais required; it cannot infer the server address on its own.Authentication or anonymous useAccessing some EPrints servers via the API requires supplying a user login and password to the server. By default, this program retrieves them from your operating system's user keyring/keychain. If the login and password for a given EPrints server does not exist from a previous run ofeprints2archives, it will ask for the user name and password, and then (unless the-Koption – or/Kon Windows – is given) store them in your keyring/keychain so that it does not have to ask again in the future. It is also possible to supply the information directly on the command line using the-uand-poptions (or/uand/pon Windows), but this is discouraged because it is insecure on multiuser computer systems. (However, if you need to reset the user name and/or password for some reason, use-uwith a user name and let it prompt for a password again.)If a given EPrints server doesnotrequire a user name and password (i.e., it allows anonymous use),supply blank valueswhen prompted for them byeprints2archivesand do not use the options-uor-p. (Empty user name and password are allowed values.)How the list of records is determinedThe EPrints records to be sent to the web archiving services will be limited to the records indicated by the option-i(or/ion Windows). If no-ioption is given, this program will use all the records available at the given EPrints server. The value of-ican be one or more integers separated by commas (e.g.,-i 54602,54604), or a range of numbers separated by a dash (e.g.,-i 1-100, which is interpreted as the list of numbers 1, 2, ..., 100 inclusive), or some combination thereof. The value of the option-ican also be a file, in which case, the file is read to get a list of identifiers.If the-loption (or/lon Windows) is given, the records will be additionally filtered to return only those whose last-modified date/time stamp is no older than the given date/time description.  Valid descriptors are those accepted by the Pythondateparserlibrary.  Make sure to enclose descriptions within single or double quotes.  Examples:eprints2archives-l"2 weeks ago"-a....
eprints2archives-l"2014-08-29"-a....
eprints2archives-l"12 Dec 2014"-a....
eprints2archives-l"July 4, 2013"-a....If the-soption (or/son Windows) is given, the records will also be filtered to include only those whoseeprint_statusfield value is one of the listed status codes.  Comparisons are done in a case-insensitive manner.  Putting a caret character (^) in front of the status (or status list) negates the sense, so thateprints2archiveswill only keep those records whose<eprint_status>value isnotamong those given. Examples:eprints2archives-sarchive-a...
eprints2archives-s^inbox,buffer,deletion-a...Both--lastmodand--statusfiltering are done after the-iargument is processed.By default, if an error occurs when requesting a record or value from the EPrints server,eprints2archiveswill keep going, moving on to the next one. Common causes of errors include missing records implied by the arguments to-i, missing files associated with a given record, and files inaccessible due to permissions errors. If the option-e(or/eon Windows) is given,eprints2archiveswill instead stop upon encountering a missing record, or missing file within a record, or similar errors. The default is to only issue warnings because this is less frustrating for most use-cases.How URLs are constructedThe list of EPrints URLs sent to web archiving sites depends on the command-line options given toeprints2archivesas well as the URLs that actually exist on the server.  In a nutshell, ifnotgiven a list of identifiers or filtering criteria, it will send URLs for every record along with the URLs of some general pages; by contrast, if the list of records is restricted somehow (by the use of-i,-l, and/or-s),eprints2archiveswillonlysend URLs related to the records identified.URLs for individual EPrints recordseprints2archivesalways tries to construct 3 URLs for every EPrint record and verifies that they exist on the EPrints server.  The URLs are as follows, whereNis the id number of the EPrint record:https://SERVER/Nhttps://SERVER/id/eprint/NThe value of the fieldofficial_url(if any) in the EPrint record.The first two typically go to the same page on an EPrint server, but web archiving services have no direct mechanism to indicate that a given URL is an alias or redirection for another, so they need to be sent as separate URLs.  On the other hand, the value ofofficial_urlmay be an entirely different URL, which may or may not go to the same location as one of the others.  For example, in the CaltechAUTHORS EPrint server, the record athttps://authors.library.caltech.edu/85447has anofficial_urlvalue ofhttps://resolver.caltech.edu/CaltechAUTHORS:20180327-085537493, but the latter is a redirection back tohttps://authors.library.caltech.edu/85447.eprints2archivesperforms basic validation on the URL values, to make sure they appear to be formally valid and filter out malformed URLs, but does not verify that the locations actually exist.Additional general URLsIfnoselection or filtering is applied (i.e., none of the options-i,-lor-sare given toeprints2archives), theneprints2archivesgathers additional URLs as follows (whereSERVERis the server hostname + post number, if any):https://SERVERhttps://SERVER/viewThe set of pageshttps://SERVER/view/X, where eachXis obtained by parsing the HTML ofhttps://SERVER/viewand extracting links to pages underhttps://SERVER/view/The set of pageshttps://SERVER/view/X/Y, where eachYis obtained by parsing the HTML ofhttps://SERVER/view/Xand extracting links to pages underhttps://SERVER/view/XOn the other hand, if selection and/or filteringarein effect (i.e., if any of the options-i,-l, and/or-sare used), theneprints2archivesonlyextracts the URLshttps://SERVER/view/X/N.htmlfor every EPrints identifierNthat is selected via-iand left after filtering with-land-s, if such URLs exist on the server.  (E.g., Caltech EPrints servers have a page athttps://SERVER/view/ids/, containing every public EPrint identifierNlinked to a page of the formhttps://SERVER/view/ids/N.html.  Other servers may have a similar section named something other than/view/ids/;eprints2archivesavoids hardwired assumptions and simply looks for pages ending inN.htmlunder/view/X/.)The general URLs from one of these two cases (the ones used if no selection or filter is applied,orthe ones used when selection and/or filtering are in effect) are combined with the URLs for individual EPrints records to produce the final set of URLs sent to web archiving destinations.How the destination is determinedeprints2archiveshas a set of built-in adapters to interact with a number of known public web archiving services. To learn which serviceseprints2archivesknows about, use the option-S(or/Son Windows). By default, the program will send EPrints record URLs to all the known services. The option-d(or/don Windows) can be used to select one or a list of destination services instead.  Lists of services should be separated by commas with no spaces between them;
e.g.,internetarchive,archivetoday.By default,eprints2archiveswill only ask a service to archive a copy of an EPrints record if the service does not already have an archived copy.  This makes sense because EPrints records usually change infrequently, and there's little point in repeatedly asking web archives to make new archives.  However, if you have reason to want the web archives to re-archive EPrints records, you can use the option-f(or/fon Windows).eprints2archiveswill use parallel process threads to query the EPrints server as well as to send records to archiving services.  By default, the maximum number of threads used is equal to 1/2 of the number of cores on the computer it is running on. The option-t(or/ton Windows) can be used to change this number.eprints2archiveswill always use only one thread per web archiving service (and since there are only a few services, only a few threads are usable during that phase of operation), but a higher number of threads can be helpful to speed up the initial data gathering step from the EPrints server.Beware that there is a lagbetween when web archives such as Internet Archive receive a URL submission and when a saved copy is made available from the archive.  (For Internet Archive, it is3-10 hours.)  If you cannot find a given EPrints page in an archive shortly after runningeprints2archives, it may be because not enough time has passed.Other command-line argumentsTo save a report of the articles sent, you can use the option-r(/ron Windows) followed by a file name.eprints2archiveswill print informative messages as it works. To limit the messages to warnings and errors only, use the option-q(or/qon Windows). Also, output is color-coded by default unless the-Coption (or/Con Windows) is given; this option can be helpful if the color control signals create problems for your terminal emulator.If given the-@argument (/@on Windows), this program will output a detailed trace of what it is doing, and will also drop into a debugger upon the occurrence of any errors.  The debug trace will be written to the given destination, which can be a dash character (-) to indicate the standard error stream (sys.stderr), or a file path.  Note, however, that ifeprints2archivesis being run withPython optimizationenabled, then-@will have no effect and will be silently ignored.If given the-Voption (/Von Windows), this program will print the version and other information to the console, and exit without doing anything else.Summary of command-line optionsThe following table summarizes all the command line options available. (Note: on Windows computers,/must be used as the prefix character instead of-):ShortLong form optMeaningDefault-aA--api-urlAUseAas the server's REST API URL⚑-dD--destDSend to destination service(s)DSend to all-e--error-outStop if encounter missing recordsKeep going-f--forceSend each record even if copy existsSkip already-archived records-iI--id-listIRecords to get (can be a file name)Fetch all EPrints records-lL--lastmodLFilter by last-modified date/timeDon't filter by date/time-q--quietDon't print general info messagesBe chatty while working-sS--statusSFilter by status(s) inSDon't filter by status-uU--userUUser name for EPrints server loginNo user name-pP--passwordUPassword for EPrints proxy loginNo password-C--no-colorDon't color-code the outputColor the console messages-K--no-keyringDon't use a keyring/keychainStore login info in keyring-S--servicesPrint list of known services and exitDo other actions instead-V--versionPrint program version info and exitDo other actions instead-@OUT--debugOUTDebugging mode; write trace toOUTNormal mode⚐ ★⚑   Required argument.⚐   To write to the console, use the character-as the value ofOUT; otherwise,OUTmust be the name of a file where the output should be written.★   Has no effect ifeprints2archivesis being run withPython optimizationenabled.Return valuesThis program exits with a return code of 0 if no problems are encountered.  It returns a nonzero value otherwise, following conventions used in shells such asbashwhich only understand return code values of 0 to 255. The following table lists the possible return values:0 = success -- program completed normally
1 = no network detected -- cannot proceed
2 = encountered a bad or missing value for an option
3 = file error -- encountered a problem with a file
4 = the user interrupted the program's execution
5 = an exception or fatal error occurredKnown issues and limitationsSome services impose severe rate limits on URL submissions, and there  is nothing thateprints2archivescan do about it.  For example, at the time of this writing,Archive.Todayonly allows 6 URLs to be submitted every 5 minutes.  If you plan on sending a large number of URLs, it may be more convenient to use a separateeprints2archivesprocess with the-doption to select only one destination, and let it run in its own terminal window.Relationships to other similar toolsOther tools exist for sending content to web archives; some are general-purpose enough that they could be used to send EPrints server contents to web archives.  To the author's knowledge,eprints2archivesis the only software designed specifically to work with EPrints servers to send content to multiple archiving destinations.The Internet Archive itselfoffers multiple ways of submitting content, including sending URLs via email, using a browser extension, and the simple-to-useSave Page Now. The latter offers the option of capturing pages more deeply if the user is logged in to their Internet Archive (IA) account.  By contrast,eprints2archivescan send the entire content of an EPrints server in one go, without requiring the user to have an IA account.Many institutions use IA'sArchive-Itservice, and Archive-It can be used to crawl EPrints server pages.  In principle, this can capture an EPrints server site more fully thaneprints2archivesbecauseeprints2archivesonly follows specific common links and pages, and misses any custom data views or additional pages (including "About" pages) that may be present on an EPrints server.  Nevertheless,eprints2archivescan be useful even for sites that use Archive-It because it asks the EPrints server itself about its records and gets URLs (such as theofficial_urlvalues) that may not be mentioned in the EPrints record views (and thus would be missed by Archive-It's "on the outside looking in" approach).  Sinceeprints2archivesby default does not send URLs that are already present in archiving destinations, it can be used in conjunction with Archive-It as a secondary or backup scheme.A number of third-party archiving tools exist for sending URLs to web archives.  One of the few that can target other archives besides IA isArchive Now.  It partly inspired the creation ofeprints2archives.  Archive Now's code for interfacing to web archives also served as initial starting points for figuring out to do the same ineprints2archives.  In terms of functionality,eprints2archivesis more special-purpose (being aimed at extracting content from EPrints servers), and has more advanced capabilities such as handling rate limits, pause-and-retry handling of errors, and use of parallel threads.Most archiving tools work only with theInternet Archive's Wayback Machine. The Ruby-basedWaybackArchivercan crawl a site given a URL or a sitemap and then send URLs to IA; however, it does not appear to attempt to recover from as many error situations aseprints2archives, and of course, lacks its EPrints-specific features.Waybackpyis a simpler tool designed to interact with IA, and while it can submit URLs to be saved, it lacks other capabilities ofeprints2archivessuch as automatically handling rate limits and error retries, as well as not being designed for extracting content from EPrints servers.  Some other similar but much simpler and less advanced IA-specific tools includesavepagenow,ia_wayback,Wayback Sitemap Archive,Save to the Wayback Machine, and thewayback apifrom HTTPreserve.archive.todayis one of the few tools for working with archives other than IA.  It is a simple command-line tool for sending content to and downloading from Archive.Today.Getting helpIf you find an issue, please submit it inthe GitHub issue trackerfor this repository.ContributingWe would be happy to receive your help and participation with enhancingeprints2archives!  Please visit theguidelines for contributingfor some tips on getting started.LicenseSoftware produced by the Caltech Library is Copyright (C) 2020–2023, Caltech.  This software is freely distributed under a BSD/MIT type license.  Please see theLICENSEfile for more information.Authors and historyThis program was initially written in mid-2020, in response to discussions in Caltech'sDigital Library Developmentgroup.The TimeMap parsing code ineprints2archives/services/timemap.pyoriginally came from theOff-Topic Memento Toolkit, by Shawn M. Jones, as it existed on 2020-07-29.  The OTMT code is made available according to the MIT license.  Acknowledgments and additional information are provided in the file header ofeprints2archives/services/timemap.py.The algorithm and some code for interacting withArchive.Todaywere borrowed fromArchiveNow, a tool developed byWeb Science and Digital Libraries Research Group at Old Dominion University.  The authors and contributors of the specific code file used (is_handler.py), as it existed on 2020-07-17, wereMohamed Aturban,Shawn M. Jones,veloute, andevil-wayback.  ArchiveNow is made available according to the MIT license.  Acknowledgments and additional information are provided in the file header ofeprints2archives/services/archivetoday.py.eprints2archivesmakes use of numerous open-source packages, without which it would have been effectively impossible to developeprints2archiveswith the resources we had.  We want to acknowledge this debt.  In alphabetical order, the packages are:aenum– advanced enumerations for Pythonappdirs– determine the appropriate app dirs on different OSesbun– a set of basic user interface classes and functionsCommonPy– a collection of commonly-useful Python functionscssselect–lxmladd-on to parse CSS3 selectorsdateparser– parse dates in almost any string formath2– HTTP/2 support library used byHTTPXhttpx– Python HTTP client library that supports HTTP/2humanize– helps write large numbers in a more human-readable formkeyring– access the system keyring service from Pythonlxml– an XML parsing library for Pythonplac– a command line argument parserpydash– “kitchen sink of Python utility libraries for doing ‘stuff’”pypubsub– a publish-and-subscribe message-passing library for Pythonpython-dateutil– additional date parsing utilitiesrich– library for writing styled text to the terminalsetuptools– library forsetup.pysidetrack– simple debug logging/tracing packagestopit– raise asynchronous exceptionstldextract– module to parse domains from URLsurllib3– HTTP client library for Pythonvalidators– data validation package for PythonAcknowledgmentsThevector artworkof a cloud and arrow contained within the logo for this repository was created byVimalfrom the Noun Project.  It is licensed under the Creative CommonsCC-BY 3.0license.The icons of operating systems used on this page were obtained fromiconsdb.com. They are distributed under aCreative Commons Attribution-NoDerivs 3.0license.This work was funded by the California Institute of Technology Library.