Aqui está o que parece funcionar para mim. Eu tive isso correndo com crontab
por um tempo e funciona para mim. Suporta RSS e Atom, eu acho. No entanto, se você pretende usá-lo, considere-o um ponto de partida. Se você adaptá-lo e a mudança for útil, sinta-se à vontade para voltar e contar à comunidade.
O resultado é uma estrutura de diretório com o nome do feed sendo o nome do diretório e as várias entradas gravadas como arquivos. Esses arquivos contêm o conteúdo inalterado e, na parte inferior, um link para a fonte. Os nomes de arquivos consistem no título do item e seu registro de data e hora, a data do arquivo é configurada para esse registro de data e hora. Dessa forma, você pode classificá-los por nome ou hora facilmente.
rss-parser.awk
:
function removeFirstTag(str) {
sub("[^>]*>", "", str)
return str
}
function extractCdata(str) {
gsub(".*<!\[CDATA\[|]]>.*", "", str)
return str
}
function cleanup(str) {
return extractCdata(removeFirstTag(str))
}
BEGIN {
written = 0
existed = 0
if (feedTitle) {
system("mkdir -p '" outDir "/" feedTitle "'")
}
}
/<\/description>|<\/content>/ {
indescr = 0
}
/<\/summary>/ {
insummary = 0
}
/<\/item>|<\/entry>/ {
gsub(/\//, "-", title)
fname = outDir "/" feedTitle "/" title " - " dateSec
fnameEnc = fname
gsub(/\$/, "\$", fnameEnc)
gsub(/"/, "\\"", fnameEnc)
if (!description) {
description = summary
}
if (link != "") {
description = description "\nLink: " link
} else if (guid != "") {
description = description "\nLink: " guid
}
write = system(binPath "/stat \"" fnameEnc "\" -c \"%u\" 1> /dev/null 2>&1")
if (write == 1) {
print description > fname
system(binPath "/touch \"" fnameEnc "\" -d \"" date "\"")
written = written + 1
} else {
existed = existed + 1
}
}
{
if (indescr == 1) {
description = description "\n" $0
}
}
/<title[ >]/ {
if (!feedTitle) {
feedTitle = cleanup($0)
system("mkdir -p '" outDir "/" feedTitle "'")
} else {
title = cleanup($0)
}
}
/<item[ >]|<entry[ >]/ {
title = ""
description = ""
summary = ""
date = ""
link = ""
guid = ""
}
/<description[ >]|<content[ >]/ {
indescr = 1
description = cleanup($0)
}
/<summary[ >]/ {
insummary = 1
summary = cleanup($0)
}
/<link[ >]/ {
link = cleanup($0)
if (index(link, "magnet") == 1) {
link = ""
}
}
/<guid[ >]|<id[ >]/ {
guid = cleanup($0)
}
/<pubDate[ >]|<published[ >]|<dc:date[ >]/ {
date = cleanup($0)
binPath "/date -d '" date "' +'%s'" | getline dateSec
}
END {
print "Done : " feedTitle " (new: " written "/old: " existed ")"
if (existed == 0 && written != 0) {
print "=== NOTE === : All entries are new. You may want to check this feed more often"
}
}
O arquivo rss-parser.cfg
consiste em linhas como
http://thatonesite.com/feed-with-nice-title
http://thatothersite.com/feed=Specific feed title is better
rss-parser.sh
:
#!/bin/sh
parse() {
url="$1"
name="$2"
echo "Start: $name ($url)"
wget -q -U "$userAgent" -O rss-news.xml $url
sed -e 's/
//g' -e 's/<\([a-z/]\)/\n</g' rss-news.xml | \
$binPath/awk \
-v "feedTitle=$name" \
-v "binPath=$binPath" \
-v "outDir=./data" \
-f rss-parser.awk | \
more
}
userAgent="Opera/9.80 (Windows NT 6.1; Win64; x64; U; de) Presto/2.10.289 Version/12.01"
binPath=/bin
cd 'dirname $0'
if [ -z "$1" ]; then
echo "================= '$binPath/date +"%d.%m.%Y %H:%M"'"
start='$binPath/date +%s'
while read line
do
if [ ! -z "$line" -a "${line:0:1}" != "#" ]; then
url=${line%%=*}
name=${line#*=}
if [ "$name" == "$url" ]; then
name=""
fi
parse "$url" "$name"
fi
done < "rss-parser.cfg"
echo "================= Took '$binPath/date -d "$start seconds ago" +%s' seconds"
else
parse "$1" "$2"
fi
Sem parâmetros, analisa rss-parser.cfg
. Caso contrário, os parâmetros são
./rss-parser.sh [<URL> [<feed name>]]
Espero que seja útil para alguém ...