Проблема форматирования блоков строк - PullRequest
1 голос
/ 29 июня 2011

Я работаю над способом автоматической загрузки параметров землетрясения из Национального центра информации о землетрясениях (USGS).К сожалению, их формат - куча дерьма, и я не думаю, что мне повезет убедить их сменить формат.Итак, мне нужно отформатировать их <pre> блок html, чтобы перевести его в табличную форму.

Но мой опыт форматирования строк ограничен, поэтому я застрял (но уверен, что есть кто-то, кто мог быесть решение).Вот пример:

curl --silent http://earthquake.usgs.gov/earthquakes/eqinthenews/2010/uu00002715/uu00002715_gcmt.php |\
sed -n '/<pre>/,/<\/pre>/p' |\
egrep -v '(#)|(pre>)' |\
egrep '(MW)|(ORIGIN)|(LAT)|(DEP)|(BEST DBLE)|(NP1)'

, который дает информацию, которую мне нужно отформатировать:

April 15, 2010, UTAH, MW=4.6
ORIGIN TIME:      23:59:42.8 0.4
LAT:41.72N 0.03;LON:110.86W 0.03
DEP: 12.5  1.8;TRIANG HDUR:  0.6
BEST DBLE.COUPLE:M0= 1.07*10**23
NP1: STRIKE=193;DIP=35;SLIP= -80

Я бы хотел такой формат:

name date       time       lon     lat   dep  dep_err Mw  M0      strike dip slip
UTAH 2010/04/15 23:59:42.8 -110.86 41.72 12.5 1.8     4.6 1.07e23 193    35  -80

Обратите внимание, что долгота должна быть преобразована в восточную долготу (отсюда и изменение знака).

Я бы хотел, чтобы решение было в командах awk, python или unix shell, но я бы развлекал ruby или perl (я просто, наверное, не пойму, что происходит).

Ответы [ 3 ]

3 голосов
/ 29 июня 2011

Почему бы просто не использовать один из их форматированных каналов XML, например , этот .Я уверен, что разобрать легче.

2 голосов
/ 29 июня 2011

Анализ html с помощью регулярных выражений обычно рассматривается как очень, очень плохая идея, поэтому я бы поддержал предложение Абизерна об использовании RSS-канала.Фактически, USGS также обеспечивает загрузку XML (см. http://earthquake.usgs.gov/earthquakes/catalogs/).

Если по какой-либо причине вы не можете этого сделать и имеет для использования html, то в качестве блока <pre>не имеет дальнейшей структуры (исключая что-то хорошее, например, используя lxml или beautifulsoup), тогда следующий python работает для этого single примера ... регулярное выражение, вероятно, очень хрупкое (и, честно говоря, cludgey) и нуждается в настройкедля обработки дальнейших примеров / исключений.

Это записывает в файл Excel, поэтому вы должны иметь возможность вставлять все это в цикл, чтобы очистить несколько страниц (играйте хорошо и проверяйте их условия, ограничивайте скорость и кэш)).

import httplib2
import re
from xlwt import Workbook

h = httplib2.Http(".cache")
url = 'http://earthquake.usgs.gov/earthquakes/eqinthenews/2010/uu00002715/uu00002715_gcmt.php'
resp, content = h.request(url, "GET")
regex = re.compile("<pre>\s*(?P<date>.* \d{2}, \d{4}), (?P<name>\w.*), MW=(?P<Mw>\d.\d).*ORIGIN TIME:\s*(?P<time>\d{2}:\d{2}:\d{2}.\d).*LAT:\s*(?P<lat>\d{2,3}.\d{2,3}[N|S]).*LON:\s*(?P<lon>\d{2,3}.\d{2,3}[W|E]).*DEP:\s*(?P<dep>\d{2,3}.\d)\s*(?P<dep_err>\d{1,3}.\d);.*M0=\s*(?P<M0>\d.\d{1,2}\*\d{1,2}\*\*\d{1,2}).*STRIKE=(?P<strike>\d{1,3}).*DIP=(?P<dip>\d{1,3}).*SLIP=\s*(?P<slip>[-|+]\d{1,3}).*NP2",re.MULTILINE|re.DOTALL)
r = regex.search(content)
data = r.groupdict()

headers = ['name', 'date', 'time', 'lon', 'lat', 'dep', 'dep_err', 'Mw', 'M0', 'strike', 'dip', 'slip']
wb = Workbook()
ws = wb.add_sheet('Quakes')

column = 0
for header in headers:
    ws.write(0, column, header)
    ws.write(1, column,data[header])
    column+=1
wb.save('quakes.xls')

Вы должны определенно использовать вместо этого XML / RSS, хотя, если можете:)

1 голос
/ 29 июня 2011

Вот скрипт awk, который поможет вам в этом. Преобразование Lon, date, M0 и т. Д. Оставлено в качестве упражнения:

curl --silent http://earthquake.usgs.gov/earthquakes/eqinthenews/2010/uu00002715/uu00002715_gcmt.php |
awk '
    BEGIN {
        FS = "[,:;= ]+"
        OFS = "^"
    }
    /<pre>/ {process=1}
    /<\/pre>/ {process=0}
    ! process {next}
    /MW=/ {
        date = $1 " " $2 " " $3
        place = $4
        mw = $NF
    }
    /^ORIGIN TIME:/ {
        otime = $3 ":" $4 ":" $5
    }
    /^LAT:.*LON:/ {
        lat = $2
        lon = $5
    }
    /^DEP:/ {
        dep = $2
        dep_err = $3
    }
    /^BEST DBLE.COUPLE:/ {
        m0 = $NF
    }
    /^NP1:/ {
        strike = $3
        dip = $5
        slip = $7
    }
    END {
        print "name", "date", "time", "lon", "lat", "dep", "dep_err", "Mw", "M0", "strike", "dip", "slip"
        print place, date, otime, lon, lat, dep, dep_err, mw, m0, strike, dip, slip
    }
' | column -s ^ -t

Выход:

name  date           time        lon      lat     dep   dep_err  Mw   M0           strike  dip  slip
UTAH  April 15 2010  23:59:42.8  110.86W  41.72N  12.5  1.8      4.6  1.07*10**23  193     35   -80
...