Как получить теги авторов книг fb2

asmadeus

Новичок
Пользователь
Июл 27, 2020
17
1
3
Привет!
Подскажите, как можно получить авторов книг fb2? Голову сломал, вроде и получаю списки, но натыкаюсь на проблему, когда автор не один, а тег middle-name (отчество) указан не для всех, тогда список неверного размера и теряется порядок

У меня выходит примерно так:
Python:
import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element
import os

PATH = 'j:\\My_book'

class FB2Parser:
    def __init__(self, folder):
        self.folder = folder
        self.filelist = self.ret_filelist_in_folder()

    def get_title_publisher_info(self, nodes):
        info = []
        for file in self.filelist:
            file = PATH + '\\'+ file
            self.root = ET.parse(file)
            self.cleanup()
            info.append(self.root.find(nodes))
        return info

    def get_text_node(self, nodes, node):
        info = self.get_title_publisher_info(nodes)
        job = []
        for element in info:
            results = []
            results.append(element.findall(node))
            if len(results[0]) == 1:
                job.append(results[0][0].text)
            elif len(results[0]) > 1:
                result = []
                for res in results[0]:
                    result.append (res.text)
                job.append(result)
            else:
                job.append('')
        return job

    def cleanup(self):
        for element in self.root.iter():
            element.tag = element.tag.partition('}')[-1]

    def ret_filelist_in_folder(self):
        filelist = []
        for file in os.listdir(self.folder):
            filelist.append(file)
        return filelist

def run():
    converter = FB2Parser(PATH)
    converter.get_text_node('./description/title-info', 'author')


if __name__ == '__main__':
    run()
 
Последнее редактирование модератором:

Berrigan

Новичок
Пользователь
Апр 21, 2022
2
3
3
XML часто содержат namespace'ы:
XML:
<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"></FictionBook>
Здесь xmlns содержит namespace.
Его нужно указывать для каждого компонента в селекторе.
Поэтому вот такой селектор:
Python:
root.find('description/title-info/author')
Превращается вот в такой:
Python:
root.find('{http://www.gribuser.ru/xml/fictionbook/2.0}description/{http://www.gribuser.ru/xml/fictionbook/2.0}title-info/{http://www.gribuser.ru/xml/fictionbook/2.0}author')
Можно сделать по-другому:
Python:
import xml.etree.ElementTree as ET
import re

root = ET.parse('book.fb2')
rootTag = root.getroot().tag  # Корневой тег: {http://www.gribuser.ru/xml/fictionbook/2.0}FictionBook

# С помощью регулярки извлечь namespace http://www.gribuser.ru/xml/fictionbook/2.0
# и положить его под пустой ключ в словарь
namespaces = {
    '': re.match(r'^\{([^\}]+)\}', rootTag).group(1)
}

# Теперь каждый раз, когда делаем find, передавать этот словарь в качестве аргумента namespaces
authorEls = root.findall('description/title-info/author', namespaces)

for authorEl in authorEls:
    firstName = authorEl.find('first-name', namespaces).text
    lastName  = authorEl.find('last-name', namespaces).text

    print(firstName, lastName)
 
Последнее редактирование:
  • Мне нравится
Реакции: asmadeus

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
933
208
43
20
Москва
Если не сложно, прикрепи fb2 на котором тестируешь
 

asmadeus

Новичок
Пользователь
Июл 27, 2020
17
1
3
Если не сложно, прикрепи fb2 на котором тестируешь
Да не вопрос
 

asmadeus

Новичок
Пользователь
Июл 27, 2020
17
1
3

Berrigan, вообще не пойму, как оно так должно работать, но работает

После моих правок так (отчество не у всех указано бывает, в чем у меня и была загвоздка):
Python:
import xml.etree.ElementTree as ET
import re


root = ET.parse('book.fb2')
rootTag = root.getroot().tag  # Корневой тег: {http://www.gribuser.ru/xml/fictionbook/2.0}FictionBook


# С помощью регулярки извлечь namespace http://www.gribuser.ru/xml/fictionbook/2.0
# и положить его под пустой ключ в словарь
namespaces = {
    '': re.match(r'^\{([^\}]+)\}', rootTag).group(1)
}


# Теперь каждый раз, когда делаем find, передавать этот словарь в качестве аргумента namespaces
authorEls = root.findall('description/title-info/author', namespaces)
res = []
for authorEl in authorEls:
    firstName = authorEl.find('first-name', namespaces).text
    middleName = authorEl.find('middle-name', namespaces)
    if middleName is not None:
        middleName = authorEl.find('middle-name', namespaces).text
    lastName = authorEl.find('last-name', namespaces).text
    if middleName is None:
        out = '{} {}'.format(firstName, lastName)
    else:
        out = '{} {} {}'.format(firstName, middleName, lastName)
    res.append(out)
print(res)

Можно теперь двинуться и далее, разбираться с правкой и сохранением тегов. Может, и до интерфейса дойду
 

Форум IT Специалистов