Уведомления

Группа в Telegram: @pythonsu

#1 Май 29, 2013 14:59:02

brimen
Зарегистрирован: 2013-05-29
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер xml..

Всем доброго дня. Мне интересно изучить Питон, решил попробовать с парсинга xml (практическая польза).
Есть xml вида

<?xml version="1.0" encoding="ISO-8859-1"?>
<Report><Lang>en</Lang>
<Page><Title>Report</Title><Icon>112</Icon>
<Item><Title>Version</Title><Icon>112</Icon><ID>257</ID><Value>AIDA64 v2.85.2400</Value></Item>
<Item><Title>Benchmark Module</Title><Icon>112</Icon><ID>266</ID><Value>3.0.492-x32</Value></Item>
<Item><Title>Homepage</Title><Icon>116</Icon><ID>259</ID><Value>http://www.aida64.com/</Value></Item>
<Item><Title>Report Type</Title><Icon>91</Icon><ID>260</ID><Value>Report Wizard [ TRIAL VERSION ]</Value></Item>
<Item><Title>Computer</Title><Icon>46</Icon><ID>261</ID><Value>comp</Value></Item>
<Item><Title>Generator</Title><Icon>47</Icon><ID>262</ID><Value>admin</Value></Item>
<Item><Title>Operating System</Title><Icon>38</Icon><ID>263</ID><Value>Microsoft Windows XP Professional 5.1.2600 (WinXP RTM)</Value></Item>
<Item><Title>Date</Title><Icon>64</Icon><ID>264</ID><Value>2013-05-29</Value></Item>
<Item><Title>Time</Title><Icon>131</Icon><ID>265</ID><Value>14:46</Value></Item>
</Page>

Как вытянуть оттуда определенные значения? Например, “Computer”. Детальный алгоритм не прошу, подскажите только методы и примерную структуру. Как парсит Python, по тегам или по значениям?
Смотрю на эту тему http://python.su/forum/topic/798/ Но там другая структура xml.

Офлайн

#2 Май 30, 2013 06:36:37

ilnur
От: Казань
Зарегистрирован: 2009-01-06
Сообщения: 524
Репутация: +  22  -
Профиль   Отправить e-mail  

Парсер xml..

я бы использовал модуль xml.etree

Офлайн

#3 Май 30, 2013 11:24:55

brimen
Зарегистрирован: 2013-05-29
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер xml..

Подскажите, каким методом?
Я пока бьюсь в потемках. Как нати не тег, а значение. Какой-то кривой xml кажется..

import xml.etree.ElementTree as etree
tree = etree.parse('D:/Report_en.xml') 
root = tree.getroot()
p = tree.find("Page")
А вот как найти значение “Computer”, с тем, чтобы вывести значение “comp”?
Ну или русскую доку..

Отредактировано brimen (Май 30, 2013 11:30:31)

Офлайн

#4 Май 30, 2013 14:15:33

pmus
Зарегистрирован: 2013-04-03
Сообщения: 46
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер xml..

А вот, мне недавно по такому же вопросу подсказали Objectify:

http://python.su/forum/topic/21391/

Офлайн

#5 Май 30, 2013 14:30:03

buddha
От:
Зарегистрирован: 2012-03-02
Сообщения: 422
Репутация: +  15  -
Профиль   Отправить e-mail  

Парсер xml..

На самом деле достаточно просто. Структура файла простая, стоит только открыть консоль и потренироваться.

Я сделал так:

from xml.etree import ElementTree
 
xml = '''<?xml version="1.0" encoding="ISO-8859-1"?>
<Report><Lang>en</Lang>
<Page><Title>Report</Title><Icon>112</Icon>
<Item><Title>Version</Title><Icon>112</Icon><ID>257</ID><Value>AIDA64 v2.85.2400</Value></Item>
<Item><Title>Benchmark Module</Title><Icon>112</Icon><ID>266</ID><Value>3.0.492-x32</Value></Item>
<Item><Title>Homepage</Title><Icon>116</Icon><ID>259</ID><Value>http://www.aida64.com/</Value></Item>
<Item><Title>Report Type</Title><Icon>91</Icon><ID>260</ID><Value>Report Wizard [ TRIAL VERSION ]</Value></Item>
<Item><Title>Computer</Title><Icon>46</Icon><ID>261</ID><Value>comp</Value></Item>
<Item><Title>Generator</Title><Icon>47</Icon><ID>262</ID><Value>admin</Value></Item>
<Item><Title>Operating System</Title><Icon>38</Icon><ID>263</ID><Value>Microsoft Windows XP Professional 5.1.2600 (WinXP RTM)</Value></Item>
<Item><Title>Date</Title><Icon>64</Icon><ID>264</ID><Value>2013-05-29</Value></Item>
<Item><Title>Time</Title><Icon>131</Icon><ID>265</ID><Value>14:46</Value></Item>
</Page>
</Report>'''  # заметить тут я дописал тэг </Report>
 
root = ElementTree.fromstring(xml)
for page in root.findall('./Page'):
    for item in page.findall('./Item'):
        if item.find('Title').text.lower() == 'computer':
            value = item.find('Value').text
            print(value)

Офлайн

#6 Май 30, 2013 14:45:41

buddha
От:
Зарегистрирован: 2012-03-02
Сообщения: 422
Репутация: +  15  -
Профиль   Отправить e-mail  

Парсер xml..

pmus
А вот, мне недавно по такому же вопросу подсказали Objectify:http://python.su/forum/topic/21391/

Несогласен, нужно просто взять файл, открыть документацию модуля xml.ertee и потренироваться.
Всё там доступно, сверх умного ничего нету.

Офлайн

#7 Май 30, 2013 14:58:44

pmus
Зарегистрирован: 2013-04-03
Сообщения: 46
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер xml..

buddha
Наверное, каждому своё. Я без objectify просто головой об стол бился, не получалось никак.
Правда, у меня и xml запутанно-своеобразный.

Офлайн

#8 Май 30, 2013 15:01:28

buddha
От:
Зарегистрирован: 2012-03-02
Сообщения: 422
Репутация: +  15  -
Профиль   Отправить e-mail  

Парсер xml..

pmus
Я без objectify просто головой об стол бился, не получалось никак.

Ну в такой ситуации позволительно))

Офлайн

#9 Июнь 3, 2013 11:29:31

brimen
Зарегистрирован: 2013-05-29
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер xml..

Спасибо за ответы! Благодаря вам, почти все получилось. Добавил обработку всех файлов в папке. Теперь затык в другом месте, пытаюсь получить значение с второй Page, но скрипт видит и проходит только по первой.

import xml.etree.ElementTree as etree
import os
import glob
f2 = open("D:report_all.txt", 'w')
directory = 'D:/folder_reports/'
fileList = glob.glob(directory + '/*.xml')
valueCPU ='--'
valueOS ='--'
valuepc ='--'
for fileName in fileList:
    root = etree.parse(fileName)
    for page in root.findall('./Page'):
        for item in page.findall('./Item'):
            if item.find('Title').text.lower() == 'computer':
                valuepc = item.find('Value').text
            elif item.find('Title').text.lower() == 'operating system':
                valueOS = item.find('Value').text
            elif item.find('Title').text.lower() == 'directx':
                valueCPU = item.find('Value').text
    f2.write(valuepc + '\t' + valueOS + '\t' + valueCPU + '\n')
f2.close()


<?xml version="1.0" encoding="ISO-8859-1"?>
<Report><Lang>en</Lang>
<Page><Title>Report</Title><Icon>112</Icon><MenuTitle></MenuTitle><MenuIcon>0</MenuIcon>
<Item><Title>Version</Title><Icon>112</Icon><ID>257</ID><Value>AIDA64 v2.85.2400</Value></Item>
<Item><Title>Benchmark Module</Title><Icon>112</Icon><ID>266</ID><Value>3.0.492-x32</Value></Item>
<Item><Title>Homepage</Title><Icon>116</Icon><ID>259</ID><Value>http://www.aida64.com/</Value></Item>
<Item><Title>Report Type</Title><Icon>91</Icon><ID>260</ID><Value>Report Wizard [ TRIAL VERSION ]</Value></Item>
<Item><Title>Computer</Title><Icon>46</Icon><ID>261</ID><Value>comp</Value></Item>
<Item><Title>Generator</Title><Icon>47</Icon><ID>262</ID><Value>admin</Value></Item>
<Item><Title>Operating System</Title><Icon>38</Icon><ID>263</ID><Value>Microsoft Windows XP Professional 5.1.2600 (WinXP RTM)</Value></Item>
<Item><Title>Date</Title><Icon>64</Icon><ID>264</ID><Value>2013-06-03</Value></Item>
<Item><Title>Time</Title><Icon>131</Icon><ID>265</ID><Value>11:31</Value></Item>
</Page>
<Page><Title>Summary</Title><Icon>46</Icon><MenuTitle>Computer</MenuTitle><MenuIcon>46</MenuIcon>
<Group><Title>Computer</Title><Icon>46</Icon>
<Item><Title>Computer Type</Title><Icon>46</Icon><ID>582</ID><Value>Ìíîãîïðîöåññîðíûé êîìïüþòåð ñ ACPI  (Mobile)</Value></Item>
<Item><Title>Operating System</Title><Icon>38</Icon><ID>513</ID><Value>Microsoft Windows XP Professional</Value></Item>
<Item><Title>OS Service Pack</Title><Icon>40</Icon><ID>540</ID><Value>[ TRIAL VERSION ]</Value></Item>
<Item><Title>Internet Explorer</Title><Icon>115</Icon><ID>564</ID><Value>8.0.6001.18702 (IE 8.0)</Value></Item>
<Item><Title>DirectX</Title><Icon>49</Icon><ID>566</ID><Value>4.09.00.0904 (DirectX 9.0c)</Value></Item>
</Group>
</Page>
</Report>

Т.е. последнее значение “Time”, такое чувство, что цикл просто не заходит во вторую группировку Page. В чем причина? Ведь for page in root.findall('./Page'): должен запустить цикл по всем Page?

В текстовом файле у меня результат
comp	Microsoft Windows XP Professional 5.1.2600 (WinXP RTM)	--

Отредактировано brimen (Июнь 3, 2013 11:30:56)

Офлайн

#10 Июнь 3, 2013 12:04:31

brimen
Зарегистрирован: 2013-05-29
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер xml..

Похоже, я нашел в чем была проблема:
for item in page.findall('.//Item'):
Надо было использовать два слеша //
“Символы // обозначают «Я хочу найти все элементы независимо от уровня вложенности, а не только непосредственные дочерние элементы». Поэтому метод возвращает список из четырёх элементов, а не из одного.”
http://ru.wikisource.org/wiki/%CF%EE%E3%F0%F3%E6%E5%ED%E8%E5_%E2_Python_3_(%CF%E8%EB%E3%F0%E8%EC)/XML
Я пытался использовать два слеша, но к Page, а не к Item.

Непростой этот Питон Точнее, не всегда явный.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version