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
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'] >>>
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
но уменьшение регистра нужна
antib
Я что-то сделал неэффективно?
antibif target in str(elem.text).lower():
antib
Я хочу выбирать те fb2, в которых в строках метаданных находится ключевое слово.
py.user.next
В этой строке объект elem.text приводишь к str, когда он и так уже str. Если же он не str, то он типа NoneType - тоже нет смысла приводить к str.
py.user.next
Отвязав данные от fb2, ты поймёшь, что не ограничиваешься средствами обработки xml. В данном случае получается, что данные из fb2 ты вытаскиваешь с помощью xml, а проверку данных ты делаешь с помощью re.
antib
Может стоит добавить проверку типа данных и при nonetype сравнение не проводить
if elem.text is not None:
antib
но что по факту мешает проверять их при помощи re сразу же?