Я работаю над тем, чтобы автоматически загружать параметры землетрясений из Национального информационного центра землетрясений (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
Обратите внимание, что долгота должна быть преобразована в восточную долготу (следовательно, смена знака).
Я хотел бы, чтобы решение unix shell
командах unix shell
awk
, python
или unix shell
, но я бы включил ruby
или perl
(я просто, вероятно, не пойму, что происходит).
Вот скрипт 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
Почему бы просто не использовать один из своих XML-форматированных каналов, таких как этот. Я уверен, что легче разобрать.
Разбор html с регулярными выражениями обычно рассматривается как очень и очень плохая идея, поэтому я бы предложил Abizern использовать RSS-канал. Фактически, USGS также предоставляет загрузки XML (см. Http://earthquake.usgs.gov/earthquakes/catalogs/).
Если по какой-то причине вы не можете этого сделать и должны использовать html, то, поскольку блок <pre>
не имеет никакой дополнительной структуры (исключая что-то приятное, например, используя lxml или beautifulsoup), для этого одного примера работает следующий python.. Регулярное выражение, вероятно, очень хрупкое (и, откровенно говоря, 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, но если вы можете :)