Анализ Python - PullRequest
       34

Анализ Python

4 голосов
/ 03 марта 2009

Я пытаюсь разобрать тег заголовка в канале RSS 2.0 на три разные переменные для каждой записи в этом канале. Используя ElementTree, я уже проанализировал RSS, так что я могу напечатать каждый заголовок [минус конечный )] с кодом ниже:

feed = getfeed("http://www.tourfilter.com/dallas/rss/by_concert_date")

for item in feed:  
 print repr(item.title[0:-1])

Я включил это, потому что, как вы можете видеть, item.title является типом данных repr (), о котором я не знаю много.

Определенный repr(item.title[0:-1]) print ed в интерактивном окне выглядит так:

'randy travis (Billy Bobs 3/21'
'Michael Schenker Group (House of Blues Dallas 3/26'

Пользователь выбирает группу, и я надеюсь, после анализа каждой item.title на 3 переменные (по одной для группы, места проведения и даты ... или, возможно, массива или я не знаю ...) выбрать только те, которые относятся к выбранной группе. Затем они отправляются в Google для геокодирования, но это уже другая история.

Я видел несколько примеров regex, и я читаю о них, но это кажется очень сложным. Это? Я подумал, что, может быть, кто-то здесь будет иметь некоторое представление о том, как именно это сделать разумным образом. Должен ли я использовать модуль re? Имеет ли значение, что выход в данный момент равен repr() с? Есть ли способ лучше? Я думал, что буду использовать цикл вроде (а это мой псевдо-Питон, просто пишу заметки):


     list = bandRaw,venue,date,latLong  
     for item in feed:  
      parse item.title for bandRaw, venue, date  
       if bandRaw == str(band)   
        send venue name + ", Dallas, TX" to google for geocoding  
        return lat,long  
      list = list + return character + bandRaw + "," + venue + "," + date + "," + lat + "," + long  
     else  

В конце мне нужно, чтобы выбранные записи в файле .csv (с разделителями-запятыми) выглядели так:

band,venue,date,lat,long  
randy travis,Billy Bobs,3/21,1234.5678,1234.5678  
Michael Schenker Group,House of Blues Dallas,3/26,4321.8765,4321.8765

Надеюсь, это не так уж и много. Я буду изучать это самостоятельно, просто подумал, что я должен написать здесь, чтобы убедиться, что он получил ответ.

Итак, вопрос в том, как мне лучше всего разобрать каждый repr(item.title[0:-1]) в feed в 3 отдельных значения, которые затем я могу объединить в файл .csv?

Ответы [ 3 ]

17 голосов
/ 03 марта 2009

Не позволяйте регулярным выражениям пугать вас ... это стоит учиться.

Учитывая приведенные выше примеры, вы можете попытаться снова вставить завершающие скобки, а затем использовать этот шаблон:

import re
pat = re.compile('([\w\s]+)\(([\w\s]+)(\d+/\d+)\)')
info = pat.match(s)
print info.groups()

('Michael Schenker Group ', 'House of Blues Dallas ', '3/26')

Чтобы получить информацию о каждой группе, просто вызовите их для объекта info:

print info.group(1) # or info.groups()[0]

print '"%s","%s","%s"' % (info.group(1), info.group(2), info.group(3))
"Michael Schenker Group","House of Blues Dallas","3/26"

Сложная вещь в регулярном выражении в этом случае - убедиться, что вы знаете все возможные символы в названии. Если в части «Michael Schenker Group» есть не-альфа-символы, вам нужно будет отрегулировать регулярное выражение для этой части, чтобы они могли.

Вышеприведенный шаблон разбивается следующим образом, который анализируется слева направо:

([\w\s]+): сопоставить любое слово или пробел (символ «плюс» означает, что должен быть один или несколько таких символов). Скобки означают, что совпадение будет записано как группа. Это часть "Michael Schenker Group". Если здесь могут быть цифры и тире, вы можете изменить части в квадратных скобках, которые являются возможными символами для набора.

\(: буквальная скобка. Обратная косая черта выходит за скобки, так как в противном случае она считается командой регулярного выражения. Это часть "(" строки.

([\w\s]+): То же, что и выше, но на этот раз соответствует части "House of Blues Dallas". В скобках они будут указаны как вторая группа.

(\d+/\d+): сопоставляет цифры 3 и 26 с косой чертой в середине. В скобках они будут указаны как третья группа.

\): закрывающая скобка для вышеуказанного.

Введение Python в регулярные выражения довольно хорошее, и вы можете провести вечер, изучая его http://docs.python.org/library/re.html#module-re. Кроме того, проверьте Dive Into Python, в котором есть дружественное введение: http://diveintopython3.ep.io/regular-expressions.html.

РЕДАКТИРОВАТЬ: см. Zacherates ниже, кто имеет некоторые хорошие правки. Две головы лучше, чем одна!

7 голосов
/ 03 марта 2009

Регулярные выражения - отличное решение этой проблемы:

>>> import re
>>> s  = 'Michael Schenker Group (House of Blues Dallas 3/26'
>>> re.match(r'(.*) \((.*) (\d+/\d+)', s).groups()
('Michael Schenker Group', 'House of Blues Dallas', '3/26')

В качестве дополнительного примечания вы можете обратиться к Универсальному анализатору каналов для обработки разборов RSS, поскольку каналы имеют плохую привычку быть искаженным.

Редактировать

Что касается вашего комментария ... Строки, которые иногда заключаются в "s", а не в "s", имеют отношение к тому факту, что вы используете repr. Repr строки обычно разделяется символом s, если только Строка содержит один или несколько символов, где вместо этого используются "s", чтобы избежать необходимости экранирования:

>>> "Hello there"
'Hello there'
>>> "it's not its"
"it's not its"

Обратите внимание на различные стили цитат.

0 голосов
/ 03 марта 2009

Что касается части repr(item.title[0:-1]), не знаю, откуда вы это взяли, но я почти уверен, что вы можете просто использовать item.title. Все, что вы делаете, это удаляете последний символ из строки и затем вызываете repr(), что ничего не делает.

Ваш код должен выглядеть примерно так:

import geocoders # from GeoPy
us = geocoders.GeocoderDotUS()

import feedparser # from www.feedparser.org
feedurl = "http://www.tourfilter.com/dallas/rss/by_concert_date"
feed = feedparser.parse(feedurl)

lines = []
for entry in feed.entries:
    m = re.search(r'(.*) \((.*) (\d+/\d+)\)', entry.title)  
    if m:
        bandRaw, venue, date = m.groups()

        if band == bandRaw:
            place, (lat, lng) = us.geocode(venue + ", Dallas, TX")
            lines.append(",".join([band, venue, date, lat, lng]))

result = "\n".join(lines)

EDIT : заменено list на lines в качестве имени переменной. list является встроенным и не должен использоваться в качестве имени переменной. К сожалению.

...