Форум сайта python.su
0
Спасибо, это похоже то, что нужно, особенно fb2desc.
Офлайн
0
Вроде получилось.
Надо будет проверить на fb2 из разных источников - если есть файлы с пустым description и по факту выполняющим его роль annotation, значит возможны и другие закидоны, но в целом заработало. Спасибо за советы.
import xml.etree.ElementTree as et def check_elem (elem, target, field = None): """Return True if target string found in element children's text attr""" if hasattr(elem, "text"): if target in str(elem.text).lower(): if not field: return True else: if field in elem.tag.lower(): return True else: print ("close, but no") else: if len (elem)>0: for child in elem: x = check_elem(child, target, field=field) if x: return True def check_descr (fname, target, field = None): """Returns True if target string found in description texts of fb2 file\ else returns False fname - file name target - string to find field - field name (element.tag), default None (all tags)""" tree = et.parse(fname) root = tree.getroot() #root[0] - description , root[1] - body target = target.lower() if field: field = field.lower() if len(root[0])>0: print ("Checking description for \'{}\'".format(target)) for thing in root[0]: x=check_elem(thing, target=target, field=field) if x: return True elif len(root[1])>0: for thing in root[1]: if "annotation" in thing.tag or "title" in thing.tag: print ("Checking annotation for \'{}\'".format(target)) for thing1 in thing: x=check_elem(elem=thing1, target=target, field=field) if x: return True else: return False
Офлайн
857
antibif hasattr(elem, "text"):
>>> import xml.etree.ElementTree as et >>> >>> doc = et.fromstring('<x/>') >>> hasattr(doc, 'text') True >>>
antibif target in str(elem.text).lower():
>>> import xml.etree.ElementTree as et >>> >>> doc = et.fromstring('<x>abc</x>') >>> doc.text 'abc' >>> type(doc.text) <class 'str'> >>>
>>> import xml.etree.ElementTree as et >>> >>> doc = et.fromstring('<x>abc<y>def1</y><y>def2</y></x>') >>> >>> lst = doc.findall('y') >>> lst [<Element 'y' at 0xb73f33c4>, <Element 'y' at 0xb73f3414>] >>> [i.text for i in lst] ['def1', 'def2'] >>>
Офлайн
0
Ок, проверка на наличие text лишняя, но уменьшение регистра нужна.
py.user.next
antib
if target in str(elem.text).lower():
>>> import xml.etree.ElementTree as et
>>>
>>> doc = et.fromstring('<x>abc</x>')
>>> doc.text
'abc'
>>> type(doc.text)
<class ‘str’>
>>>
In [1]: import xml.etree.ElementTree as et In [2]: doc1 = et.fromstring("<x>abc</x>") In [3]: doc1.text Out[3]: 'abc' In [4]: doc2 = et.fromstring("<z>AbC</z>") In [5]: doc2.text Out[5]: 'AbC' In [6]: doc2.text == doc1.text Out[6]: False In [7]: doc2.text.lower() == doc1.text Out[7]: True
Отредактировано antib (Июль 30, 2014 21:19:30)
Офлайн
857
antib
но уменьшение регистра нужна
Офлайн
0
Ну да. Я хочу выбирать те fb2, в которых в строках метаданных находится ключевое слово. Я что-то сделал неэффективно?
Офлайн
857
antib
Я что-то сделал неэффективно?
antibif target in str(elem.text).lower():
antib
Я хочу выбирать те fb2, в которых в строках метаданных находится ключевое слово.
Отредактировано py.user.next (Июль 31, 2014 23:11:22)
Офлайн
0
py.user.next
В этой строке объект elem.text приводишь к str, когда он и так уже str. Если же он не str, то он типа NoneType - тоже нет смысла приводить к str.
py.user.next
Отвязав данные от fb2, ты поймёшь, что не ограничиваешься средствами обработки xml. В данном случае получается, что данные из fb2 ты вытаскиваешь с помощью xml, а проверку данных ты делаешь с помощью re.
Отредактировано antib (Авг. 1, 2014 21:59:35)
Офлайн
857
antib
Может стоит добавить проверку типа данных и при nonetype сравнение не проводить
if elem.text is not None:
antib
но что по факту мешает проверять их при помощи re сразу же?
Отредактировано py.user.next (Авг. 2, 2014 13:54:41)
Офлайн
0
Это всё в общем случае правильно и интересно к обдумыванию, но реализовывать я это буду уже после того, как доделаю оставшееся. А лучше применю к своей основной поделке, от которой я отвлёкся на fb2. В противном случае решение практического частного случая будет отодвинуто в будущее ради более универсального решения. А то глядишь к поиску просто тегов поттянется создание sqlite базы на все fb2 в папке т.к. надо же их куда-то девать, что бы не искать по всем файлам заново и так далее.
Отредактировано antib (Авг. 3, 2014 19:37:10)
Офлайн