diff --git a/src/bibapi/schemas/bookdata.py b/src/bibapi/schemas/bookdata.py index 5d3928b..3ef16fa 100644 --- a/src/bibapi/schemas/bookdata.py +++ b/src/bibapi/schemas/bookdata.py @@ -82,10 +82,12 @@ class BookData: setattr(self, key, value) def get_book_type(self) -> str: - if "Online" in self.pages: - return "eBook" - else: - return "Druckausgabe" + if isinstance(self.media_type, str): + if "Online" in self.pages: + return "eBook" + else: + return "Druckausgabe" + return None def from_string(self, data: str) -> "BookData": ndata = json.loads(data) diff --git a/src/bibapi/schemas/marcxml.py b/src/bibapi/schemas/marcxml.py index 526e6f7..e966aa2 100644 --- a/src/bibapi/schemas/marcxml.py +++ b/src/bibapi/schemas/marcxml.py @@ -54,3 +54,15 @@ class SearchRetrieveResponse: numberOfRecords: int records: List[Record] = field(default_factory=list) echoedSearchRetrieveRequest: Optional[EchoedSearchRequest] = None + + +@dataclass +class FormattedResponse: + title: str + edition: Optional[str] = None + publisher: Optional[str] = None + year: Optional[str] = None + authors: List[str] = field(default_factory=list) + isbn: List[str] = field(default_factory=list) + ppn: Optional[str] = None + libraries: List[str] = field(default_factory=list) diff --git a/src/bibapi/sru.py b/src/bibapi/sru.py index 1e571a0..6df69fd 100644 --- a/src/bibapi/sru.py +++ b/src/bibapi/sru.py @@ -18,15 +18,6 @@ from .schemas.marcxml import ( SubField, ) -# ----------------------- -# Dataclasses -# ----------------------- - - -# ----------------------- -# Parser -# ----------------------- - ZS = "http://www.loc.gov/zing/srw/" MARC = "http://www.loc.gov/MARC21/slim" NS = {"zs": ZS, "marc": MARC} @@ -375,18 +366,44 @@ def book_from_marc(rec: MarcRecord) -> BookData: ) -class SWBData(Enum): +class SWBSchema(Enum): URL = "https://sru.k10plus.de/opac-de-627!rec=1?version=1.1&operation=searchRetrieve&query={}&maximumRecords=100&recordSchema=marcxml" ARGSCHEMA = "pica." NAME = "SWB" -class DNBData(Enum): +class DNBSchema(Enum): URL = "https://services.dnb.de/sru/dnb?version=1.1&operation=searchRetrieve&query={}&maximumRecords=100&recordSchema=MARC21-xml" ARGSCHEMA = "" NAME = "DNB" +class KOBVSchema(Enum): + URL = "https://sru.kobv.de/k2?version=1.1&operation=searchRetrieve&query={}&startRecord=1&maximumRecords=100&recordSchema=marcxml" + ARGSCHEMA = "dc." + NAME = "KOBV" + + +class HebisSchema(Enum): + URL = "http://sru.hebis.de/sru/DB=2.1?query={}&version=1.1&operation=searchRetrieve&stylesheet=http%3A%2F%2Fsru.hebis.de%2Fsru%2F%3Fxsl%3DsearchRetrieveResponse&recordSchema=marc21&maximumRecords=100&startRecord=1&recordPacking=xml&sortKeys=LST_Y%2Cpica%2C0%2C%2C" + ARGSCHEMA = "pica." + NAME = "HEBIS" + REPLACE = {" ": "+", "&": "%26", "=": "+%3D+"} + + +class OEVKSchema(Enum): + URL = "https://sru.k10plus.de/opac-de-627-2?version=1.1&operation=searchRetrieve&query={}&maximumRecords=100&recordSchema=marcxml" + ARGSCHEMA = "pica." + NAME = "OEVK" + + +class HBZSchema(Enum): + URL = "https://eu04.alma.exlibrisgroup.com/view/sru/49HBZ_NETWORK?version=1.2&operation=searchRetrieve&recordSchema=marcxml&query={}&maximumRecords=100&recordSchema=marcxml" + ARGSCHEMA = "alma." + NAME = "HBZ" + + + RVK_ALLOWED = r"[A-Z0-9.\-\/]" # conservative char set typically seen in RVK notations @@ -489,11 +506,14 @@ def find_newer_edition( return [best] if best else None -class Api: - def __init__(self, site: str, url: str, prefix: str): +class _Api: + def __init__( + self, site: str, url: str, prefix: str, replace: Optional[Dict[str, str]] = None + ): self.site = site self.url = url self.prefix = prefix + self.replace = replace or {} # Reuse TCP connections across requests for better performance self._session = requests.Session() # Slightly larger connection pool for concurrent calls @@ -522,13 +542,11 @@ class Api: query_args = args # query_args = [f"{self.prefix}{arg}" for arg in query_args] query = "+and+".join(query_args) - query = query.replace(" ", "%20").replace("&", "%26") - # query_args = [arg for arg in query_args if not arg.endswith("=")] - # query = "+and+".join(query_args) - # query = query.replace(" ", "%20").replace("&", "%26") - # insert the query into the url url is - url = self.url.format(query) + for old, new in self.replace.items(): + query = query.replace(old, new) + url = self.url.format(query) + print(url) headers = { "User-Agent": f"{self.site} SRU Client, ", "Accept": "application/xml", @@ -568,17 +586,98 @@ class Api: return "" -class SWB(Api): +class SWB(_Api): def __init__(self): - self.site = SWBData.NAME.value - self.url = SWBData.URL.value - self.prefix = SWBData.ARGSCHEMA.value + self.site = SWBSchema.NAME.value + self.url = SWBSchema.URL.value + self.prefix = SWBSchema.ARGSCHEMA.value super().__init__(self.site, self.url, self.prefix) -class DNB(Api): +class DNB(_Api): def __init__(self): - self.site = DNBData.NAME.value - self.url = DNBData.URL.value - self.prefix = DNBData.ARGSCHEMA.value + self.site = DNBSchema.NAME.value + self.url = DNBSchema.URL.value + self.prefix = DNBSchema.ARGSCHEMA.value super().__init__(self.site, self.url, self.prefix) + + +class KOBV(_Api): + def __init__(self): + self.site = KOBVSchema.NAME.value + self.url = KOBVSchema.URL.value + self.prefix = KOBVSchema.ARGSCHEMA.value + super().__init__(self.site, self.url, self.prefix) + + +class HEBIS(_Api): + def __init__(self): + self.site = HebisSchema.NAME.value + self.url = HebisSchema.URL.value + self.prefix = HebisSchema.ARGSCHEMA.value + self.replace = HebisSchema.REPLACE.value + super().__init__(self.site, self.url, self.prefix, self.replace) + + +class OEVK(_Api): + def __init__(self): + self.site = OEVKSchema.NAME.value + self.url = OEVKSchema.URL.value + self.prefix = OEVKSchema.ARGSCHEMA.value + super().__init__(self.site, self.url, self.prefix) + + +class HBZ(_Api): + """ + Small wrapper of the SRU API used to retrieve data from the HBZ libraries + + All fields are available [here](https://eu04.alma.exlibrisgroup.com/view/sru/49HBZ_NETWORK?version=1.2) + + Schema + ------ + HBZSchema: + query prefix: alma. + """ + + def __init__(self): + self.site = HBZSchema.NAME.value + self.url = HBZSchema.URL.value + self.prefix = HBZSchema.ARGSCHEMA.value + super().__init__(self.site, self.url, self.prefix) + + def search(self, query_args: Union[Iterable[str], str]): + arguments = + +# async KVK class: +class KVK: + def __init__(self): + self.k10plus = SWB() + self.dnb = DNB() + self.hebis = HEBIS() + self.oevk = OEVK() + self.hbz = HBZ() + self.kobv = KOBV() + + def close(self): + self.k10plus.close() + self.dnb.close() + self.hebis.close() + self.oevk.close() + self.hbz.close() + self.kobv.close() + + def __del__(self): + self.close() + + # async def get_all(self, query_args: Union[Iterable[str], str]) -> Dict[str, List[BookData]]: + async def get_all( + self, query_args: Union[Iterable[str], str] + ) -> Dict[str, List[BookData]]: + results = {} + results["K10Plus"] = self.k10plus.getBooks(query_args) + results["DNB"] = self.dnb.getBooks(query_args) + results["HEBIS"] = self.hebis.getBooks(query_args) + results["OEVK"] = self.oevk.getBooks(query_args) + results["HBZ"] = self.hbz.getBooks(query_args) + results["KOBV"] = self.kobv.getBooks(query_args) + return results