вложенные циклы for очень медленные с красивым супом

#python #xml #beautifulsoup

#python #xml #beautifulsoup

Вопрос:

У меня есть XML-файл с деревом, примерно таким. Root имеет много A, у каждого A есть много B, у каждого B есть много информации:

 <root>
  <a>
    <b>
      <info>
        <stuff>
          ...
        </stuff>
      </info>
      <info>
        <stuff>
          ...
        </stuff>
      </info>
      ...
    </b>
  </a>
  ...
  <a>
    <b>
      <info>
        <stuff>
          ...
        </stuff>
      </info>
      <info>
      </info>
      ...
    </b>
  </a>
  ...
</root>
  

Я извлекаю данные для ввода в базу данных. Каждая запись в БД создается из разных тегов на разной глубине. У меня есть серия циклов for для перехода в узел с наименьшей глубиной, используя BeautifulSoup для анализа xml. Я опустил вставку ORM и DB из кода, потому что это не то место, где находится узкое место.

 for fn in glob.glob('/dir/*.xml'):
    soup = BeautifulSoup(fn)

    all_a = soup.find_all('a')

    for a in all_a:
      blah = a.something.string
      blah2 = a.somethingelse.string
      all_b = a.find_all('b')

      for b in all_b:
         blah3 = b.somethingagain.string
         blah4 = b.again.string
         all_info = b.find_all('info')

         for info in all_info:
            blah5 = info.find('name')
            blah6 = info.almostdone.string

            #this is what gets inserted into db
            return (blah, blah2, blah3, blah4, blah5, blah6) 
  

Я перебираю каталог с тысячами XML-файлов с помощью glob. Этот подход продвигается очень медленно. Каждый оператор return будет новой строкой в моей базе данных.

Я подумал, что, возможно, использование понимания списков может ускорить процесс, но это просто очень неаккуратно с множеством глубин XML-объектов.

Есть ли способ сделать это быстрее? Возможно, лучший подход с использованием BeautifulSoup.

Комментарии:

1. lxml будет намного быстрее, чем BeautifulSoup.

2. Я заметил, что вы возвращаетесь из своего самого внутреннего цикла. Означает ли это, что вам нужен только первый тег «info» в первом теге «b» в первом теге «a»? Если это так, то нет причин для find_all find было бы достаточно.

3. @StevenRumbalski Мне нужно получить информацию из каждого тега A и для каждого дочернего элемента этого тега. Если я не вернусь из самого внутреннего цикла, я не получу правильных результатов. Я не мог заставить его работать с just .find. Я получаю ошибку навигации по строке.