Форум сайта python.su
0
приветствую всех.
у меня проблема с парсингом лог-файлов от онлайн игры fonline.
пример сообщений лога:
16:37:17 • Идет соединение с сервером.
16:40:11 • Вы видите: Деревянная стена.
16:40:15 • Рация 0> ..senjor pisun..
16:48:56 • Человек в кожаной куртке ранен на 36 жизней.
16:48:56 • Человек в кожаной куртке получил ранение в левую руку на 36 жизней.
16:48:52 • Женщина в кожаной куртке была серьезно ранена в пах на 67 жизней. Ее будущие дети под угрозой, так как она падает на землю как куча тряпок.
16:49:56 • Женщина в кожаной куртке критично ранена на 2 жизней без защиты брони, удар опрокидывает женщину на землю.
Мне нужно:
во-первых определить какие из сообщений обычные (не содержат логов боя)
во-втроых определить логи боя и вытащить имена раненых + куда их ударили + на сколько
в третьих определить тех кого критически ранили и опять же куда и на сколько
при беглом анализе видно что обычные сообщеничя отличаются от боевых специальными фразами типа: “ранен на 36 жизней”, “критично ранена на 2 жизней”
я попытался описать грамматику, но при работе моей программы все сообщения попадают в разряд “обычные” (simple). подскажите как исправить ошибку.
import codecs
from pyparsing import *
def crit():
print “crit”
def simple():
print “simple”
#+ combat_aim + combat_dmg
if __name__ == ‘__main__’:
rus_lowercase = u“йцукенгшщзхъфывапролджэячсмитьбю”
rus_uppercase = u“ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ”
eng_lowercase = u“qwertyuiopasdfghjklzxcvbnm”
eng_uppercase = u“QWERTYUIOPASDFGHJKLZXCVBNM”
all_rus_letters = rus_lowercase + rus_uppercase
all_eng_letters = eng_lowercase + eng_uppercase
all_letters = all_rus_letters + all_eng_letters
time = Group(Word(nums) + “:” + Word(nums) + “:” + Word(nums))
time.setName(“time”)
message_delimiter = Suppress(Literal(“•”))
#nick = ZeroOrMore(Word(all_eng_letters + nums)) + ZeroOrMore(Word(all_rus_letters + nums))
nick = OneOrMore(Word(all_rus_letters + nums))
combat_crit = Suppress(Literal(“был серьезно ранен”)) ^ \
Suppress(Literal(“критично ранена”)) ^ \
Suppress(Literal(“выдержал критичное попадание”)) ^ \
Suppress(Literal(“была серьезно ранена”)) ^ \
Suppress(Literal(“выдержала критичное попадание”)) ^ \
Suppress(Literal(“перенесла серьезное ранение”))
combat_aim = Literal(“в голову”) ^ \
Literal(“в левую руку”) ^ \
Literal(“в правую руку”) ^ \
Literal(“в левую ногу”) ^ \
Literal(“в правую ногу”) ^ \
Literal(“в пах”) ^ \
Literal(“в глаза”)
combat_dmg = Suppress(Literal(“на”)) + Word(nums) + Suppress(Literal(“жизней”))
message = Optional(ZeroOrMore(Word(all_rus_letters + nums)))
critshot_record = time + message_delimiter + nick + combat_crit + message
critshot_record.setParseAction(crit)
simple_msg_record = time + message_delimiter + message
simple_msg_record.setParseAction(simple)
record = simple_msg_record ^ critshot_record
fileObj = codecs.open(“D:\Games\FOnline Requiem\messagebox\messbox_2013.01.06_22-09-51.txt”, “r”, “cp1251” )
for line in fileObj.readlines():
print line
rec = record.parseString(line)
print rec
Офлайн
0
Используйте регулярные выражения.
import re simple = [] numInString = re.compile('\d+') if ( numInString.findall(your_line) ): simple.append(your_line)
Офлайн
0
rus_lowercase = u“йцукенгшщзхъфывапролджэячсмитьбю”Все это и многое другое в вашем коде делается с помощью регулярных выражений намного проще.
rus_uppercase = u“ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ”
eng_lowercase = u“qwertyuiopasdfghjklzxcvbnm”
eng_uppercase = u“QWERTYUIOPASDFGHJKLZXCVBNM”
Офлайн
0
ники регистрозависимые
знаки препинания нужнеы чтобы сразу отсеять ненужную информацию (после запятой инфа не нужна)
надо просто описать грамматику, но у меня этого сделать не получается… не вижу своей ошибки
на более простых текстах описать грамматику получаелось без особого дебага. но тут получается что боевая грамматика поглощается простой грамматикой (включает в себя полностью). либо такие тексты не получится распарсить этой библиотекой в принципе, либо я не знаю какой-то фишки которая сделает боевую грамматику более приоритетной для парсера
Офлайн
857
avmartuginесли есть слово, начинающееся с “ранен”, то это строка боя
во-первых определить какие из сообщений обычные (не содержат логов боя)
во-втроых определить логи боя и вытащить имена раненых + куда их ударили + на сколько
в третьих определить тех кого критически ранили и опять же куда и на сколько
avmartuginэто куда ранен ?
16:48:56 • Человек в кожаной куртке ранен на 36 жизней.
Отредактировано py.user.next (Фев. 26, 2013 00:59:59)
Офлайн
0
py.user.nextну я вот это и попытался сделать, но не получилось.
Офлайн
857
давай набор ников, которые принадлежат и которые не принадлежат грамматике
Офлайн
0
Человек в кожаной куртке
Сучка
Mechan
DeaDNick
Frost Nova
mr.tesla
freeman1
вот такие могут быть ники
т.е. любые буквы латиницы + русские, также точка и пробел
в общем в сообщении боя для критавсе что после игрового времени и знака ( • ) и до слов:
“был серьезно ранен”
“критично ранена”
“выдержал критичное попадание”
“была серьезно ранена”
“выдержала критичное попадание”
“перенесла серьезное ранение” является ником
Отредактировано avmartugin (Март 1, 2013 07:40:14)
Офлайн
857
<сообщение боя> ::= <юнит><удар>
<юнит> ::= <слово>{<разделитель><слово>}
<удар> ::= <степень урона><жизни> | <степень урона><место урона><жизни>
<степень урона> ::= "ранен" | "получил ранение" | "критично ранен"
<место урона> ::= "в левую руку" | "в пах"
<жизни> ::= "на" <число> "жизней"
Отредактировано py.user.next (Март 3, 2013 16:14:53)
Офлайн