Уведомления

Группа в Telegram: @pythonsu

#1 Май 8, 2013 15:15:05

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

Коллеги, помогите правильно разобрать XML, вопрос скорее архитектурный

Дорогие коллеги-товарищи, очень нуждаюсь в помощи.

В Питоне я, в общем-то, новичок, но полюбил его сразу, и считаю его почти идеальным инструментом для решения моей задачи.

Пишу привод для торговли на бирже, и сейчас разбираю биржевые данные, которые приезжают в формате “почти” XML (без заголовка)

Данные примерно такие:

<securities><security secid="2326" active="true"><seccode>LK13500BE3</seccode><shortname>LKOH-6.13M140513CA 13500</shortname><decimals>0</decimals><market>4</market><sectype>OPT</sectype><opmask usecredit="no" bymarket="no" nosplit="no" immorcancel="no" cancelbalance="yes"/><minstep>1</minstep><lotsize>1</lotsize><point_cost>100</point_cost></security><security secid="2327" active="true"><seccode>RU000A0JTFZ1</seccode><shortname>СтаврКрай1</shortname><decimals>2</decimals><market>1</market><sectype>BOND</sectype><opmask usecredit="yes" bymarket="no" nosplit="yes" immorcancel="yes" cancelbalance="yes"/><minstep>0.01</minstep><lotsize>1</lotsize><point_cost>10</point_cost></security></securities>
<quotations><quotation secid="907"><accruedintvalue>0.00</accruedintvalue><closeprice>6510</closeprice><volatility>22.06</volatility><theoreticalprice>6790</theoreticalprice><buydeposit>9397.46</buydeposit><selldeposit>5328.24</selldeposit></quotation></quotations>

Код такой:

#coding=utf8
import sqlite3
import xml.etree.cElementTree as ET
## now parse
encs = '<?xml version="1.0" encoding="UTF-8"?>'
mybase = sqlite3.connect('stock.db')
sqlres = mybase.execute('SELECT [recv].[rawtext] FROM [recv] ORDER BY [time] ASC') # LIMIT 10
for row in sqlres:
    sqlanswer = encs + str(row[0])
    try:
        root = ET.fromstring(sqlanswer)
    except:
        print('Error parsing XML: %s' % sqlanswer) # если где-то вдруг косяк
        pass
    for elem in root.iter():
        print(' TAG -> ' + elem.tag, end='')
        if elem.text:
            print(' TEXT = ' + elem.text, end='') # TEXT
        for attr in elem.attrib:
            print(' ATTR ' + attr + " = " + elem.attrib[attr])

Получаю вывод:

 TAG -> seccode TEXT = TATNP TAG -> shortname TEXT = Татнфт 3ап TAG -> decimals TEXT = 2 TAG -> market TEXT = 1 TAG -> sectype TEXT = SHARE TAG -> opmask ATTR cancelbalance = yes
ATTR bymarket = yes
ATTR usecredit = yes
ATTR nosplit = yes
ATTR immorcancel = yes
TAG -> minstep TEXT = 0.01 TAG -> lotsize TEXT = 10 TAG -> point_cost TEXT = 1 TAG -> security ATTR active = true
ATTR secid = 29

 TAG -> quotations TAG -> quotation ATTR secid = 907
TAG -> accruedintvalue TEXT = 0.00 TAG -> closeprice TEXT = 6510 TAG -> volatility TEXT = 22.06 TAG -> theoreticalprice TEXT = 6790 TAG -> buydeposit TEXT = 9397.46 TAG -> selldeposit TEXT = 5328.24

Есть целый набор возможных тэгов, в данном случае я привожу только <seccode>, который описывает список торгуемых бумаг и <quotations> - цены.

Я упёрся в то, что 1) описания приходят пачками, 2) не знаю, как же их ПРАВИЛЬНО вернуть из парсера, чтобы затем заполнить tuples для дальнейшего использования.

То ли список списков тут нужен, то ли…. неясно, в общем. Подскажите?!

Как потом разбирать, тоже вопрос. if TAG == ‘seccode’ then…. и так 55 линий? Глупо.

Прошу совета.

Отредактировано pmus (Май 8, 2013 15:35:49)

Офлайн

#2 Май 8, 2013 15:47:04

s0rg
От:
Зарегистрирован: 2011-06-05
Сообщения: 777
Репутация: +  25  -
Профиль   Отправить e-mail  

Коллеги, помогите правильно разобрать XML, вопрос скорее архитектурный

Какие именно данные вам нужны из этой пачки?
Кроме кортежей есть еще словари и именованные кортежи (namedtuple)

Офлайн

#3 Май 8, 2013 16:04:52

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

Коллеги, помогите правильно разобрать XML, вопрос скорее архитектурный

Там все данные важны, разве что OPMASK черт бы с ними.

Пока представляю что-то типа:

sec[n]['name', 'shortname', 'minstep', 'lotsize', 'point_cost'] = 'TATNP', ' Татнфт 3ап', '0.01', '10', '1'
или
quotations['TATNP', 'lastprice'] += lastprice

или даже

class sec(object):
    ''' class that handles security '''
    def __init__(self, secname):
        self.secname = secname
        self.last = []
        self.stakan = []
    def addlastprice(self, price):
        self.last.append (price)
    def addstakan(self, price):
        self.stakan.append (price)
rim = sec('RIM3')
rim.addlastprice(145000)
rim.addlastprice(144000)
rim.addlastprice(144300)
print rim.last

В общем, чего-то я серьезно не впиливаю.


Отредактировано pmus (Май 9, 2013 09:09:36)

Офлайн

#4 Май 8, 2013 16:05:23

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Коллеги, помогите правильно разобрать XML, вопрос скорее архитектурный

Проще использовать lxml и его модуль objectify

# -*- coding: utf-8 -*-
from lxml import etree, objectify
 
 
text = '<securities>...</securities>'
securities = objectify.fromstring(text)
for security in securities.security:
    print(
        security.get('secid'), 
        security.shortname.text, 
        security.market,
        security.opmask.get('usecredit'),
        # ...
    )
 

Офлайн

#5 Май 8, 2013 18:48:26

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

Коллеги, помогите правильно разобрать XML, вопрос скорее архитектурный

reclosedev, спасибище Вам огромное! Наконец-то мои жалкие потуги сдвинулись с места.

Офлайн

#6 Май 9, 2013 14:08:25

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

Коллеги, помогите правильно разобрать XML, вопрос скорее архитектурный

seclist = {}
...
    try:
        for security in tree.security:
            seclist[security.seccode] = (
            {'seccode':security.seccode, 'secid': security.get('secid'), 'shortname': security.shortname, 'market': security.market})
    except:
        pass
....
print(seclist['RIM3'])
....
>{'shortname': 'RTS-6.13', 'seccode': 'RIM3', 'secid': '4016', 'market': 4}

А как мне теперь вытащить только ‘secid’ из списка?
Что-то вроде:
print(seclist['RIM3'].'secid')
>4016
Или, может быть, я вообще зря список сюда приплел?

Отредактировано pmus (Май 9, 2013 14:21:43)

Офлайн

#7 Май 9, 2013 15:08:57

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

Коллеги, помогите правильно разобрать XML, вопрос скорее архитектурный

Ну, конечно!

 print(seclist['RIM3']['secid'])

Отредактировано pmus (Май 9, 2013 15:09:19)

Офлайн

#8 Май 18, 2013 20:53:53

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

Коллеги, помогите правильно разобрать XML, вопрос скорее архитектурный

Вдогонку (для тех, кому попадется подобная задача)

tree = objectify.fromstring (text)
def result():
	global tree
	print tree.text
	print tree.attrib
	#и так далее...
def server_status():
	global tree
	#и так далее...
def security():
	global tree
	for s in tree.security :
		seclist.append (s.seccode)
                            secdict [s.seccode] = (
                           { 'secid' : s.get ('secid') , 'active' : s.get ('active') , 'seccode' : s.seccode ,
	#и так далее...
options = {'result' : result,
           'server_status' : server_status,
           'security' : security
}
options[tree.tag]()

Отредактировано pmus (Май 18, 2013 20:54:58)

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version