LINUX.ORG.RU
ФорумAdmin

Вопрос про парсинг на баше от падавана

 ,


0

0

Привет, хочу написть скрипт который бы парсил книги в txt но зашел в тупик

#!/bin/bash

MAINURL=http://url.com
RAZDEL=/fantastic/

Не понятно сразу 2 вещи:

1. Как определить $nomer чтобы он был например от 1 до 10?
BOOKLINK=$(curl '$MAINURL$RAZDEL$nomer' | grep 'bookimage' | grep -o «a href*[^>]*/» | cut -d '«' -f2

2. Как потом передать выхлоп $BOOKLINK в следующую команду?(В выхлопе будет что то вроде /B13131)

Вот так?
TXTLINK=$(curl '$MAINURL$BOOKLINK' | grep 'txt' | grep -o „a href*[^>]*/“ | cut -d '»' -f2

Если да, то в конце скрипта, по идее будет вот так?(без других переменных) wget $TXTLINK

Вы лучше опишите что вы хотите сделать. Т.е входные данные, есть файл со ссылками или url адрес страницы. Ну и что вы хотите сделать, скачивать книги по ссылкам, указанным в файле или скачивать url страницу, разбирать её, находить на неё ссылки с книгами в текстовых файлах и скачивать их ?

Как определить $nomer чтобы он был например от 1 до 10?

for i in {1..10} ; do echo $i ; done
kostik87 ★★★★★
()
Последнее исправление: kostik87 (всего исправлений: 1)

Раздел-одел. Убивать за переменные транслитом.

Человек выше правильно сказал: недостаточно входных данных для помощи.

NeverLoved ★★★★★
()
Ответ на: комментарий от kostik87

1 шаг - BOOKLINK, получаем ссылки на страницу самих книг. Получается выхлоп /13131
2 шаг подстановка главного url и выхлопа из 1 шага. Затем нахождение прямой ссылки на скачиваение книги в формате txt с помощью curl и grep
3 шаг скачивание всех txt

censured
() автор топика
Ответ на: комментарий от kostik87

for i in {1..10} ; do echo $i ; done

делал так, но не пойму как потом подставить такое значение в конец '$MAINURL$RAZDEL$i' погуглил около часа попробовал сам, но к сожалению так и не разобрался

censured
() автор топика
Ответ на: комментарий от censured

на флибусте тех же книг разве нет?

Deleted
()
Ответ на: комментарий от kostik87
#!/bin/bash

MAINURL=http://tululu.org
RAZDEL=/fantastic/

for i in {1..10}
do
   BOOKLINK=$(curl '$MAINURL$RAZDEL$i' \
   | grep 'bookimage' \
   | grep -o "a href*[^>]*/" \
   | cut -d '"' -f2)
done

При выполнении пишет

curl: (6) Couldn't resolve host '$MAINURL$RAZDEL$i'
curl: (6) Couldn't resolve host '$MAINURL$RAZDEL$i'
curl: (6) Couldn't resolve host '$MAINURL$RAZDEL$i'

censured
() автор топика
Ответ на: комментарий от kostik87

Ок, немного перефразирую.

С самого начала я не мог понять как сделать переменную которая была бы от 1 до 10. Погуглив нашел то же самое что вы написали:

for i in {1..10} ; do echo $i ; done

Но из этого сразу вытек вопрос номер 2, как весь этот выхлоп передать на выполнение следующей команды. В данный момент с вашей помощью получилось сделать

#!/bin/bash


MAINURL=http://tululu.org
RAZDEL=/fantastic/

for i in {1..10}
do
   curl 'http://tululu.org/fantastic/$i/' \ | grep 'bookimage' | grep -o "a href*[^>]*/" | cut -d '"' -f2 
done

Если внутрь for i вместо http://tululu.org/fantastic/$i/ подставить $MAINURL$RAZDEL$i/ то идет ошибка curl: (6) Couldn't resolve host '$MAINURL$RAZDEL$i'

И по прежнему не понятно как выхлоп for i in ... done передать на обработку следующей команде

censured
() автор топика
Ответ на: комментарий от censured
#!/bin/sh
URL="http://tululu.org/"
RAZDEL=fantastic
PAGE_TMP=/tmp/page.tmp 
BOOK_TMP=/tmp/book.tmp
BOOKS_DIR=/tmp/books
test -d $BOOKS_DIR || mkdir $BOOKS_DIR
for page in {1..10}
do
   echo -e "======================================\nОбрабатывается страница номе $page\n======================================"
   wget "${URL}/${RAZDEL}/$page" -O- 2> /dev/null | iconv -f cp1251 -t utf-8 -o $PAGE_TMP
   grep 'bookimage' $PAGE_TMP | while read BOOK 
   do
      echo $BOOK | sed s/alt.*//gi \
      | sed s/.*'><a '//gi \
      | sed s/'><img'//gi \
      | sed s/'\" '/'\"\n'/gi > $BOOK_TMP
      . $BOOK_TMP
      ID=`echo ${href//\/} | sed s/^b//`
      wget "${URL}/$href" -O-  2> /dev/null \
      | iconv -f cp1251 -t utf-8 \
      | grep 'скачать txt' > /dev/null && \
      echo " * Книга $title" ; \
      wget -c "${URL}/txt.php?id=${ID}" -O ${BOOKS_DIR}/"${title}.txt"  2> /dev/null
   done
done

#href="/txt.php?id=18919"
kostik87 ★★★★★
()

если несколько переменных подряд, то надо так:

${var1}${var2}
dikiy ★★☆☆☆
()
Ответ на: комментарий от censured

Я ваш код не проверял и не вчитывался, просто скопировал строку, которую вы привели, добавив лишь переменную цикла $i.

А так, да, вам правильно уже ответили ковычки должны быть двойные ", а не одинарные '.

При использовании одинарных ковычек не происходит подстановка значений переменных.

kostik87 ★★★★★
()
Ответ на: комментарий от kostik87

В процессе исполнения писал Bad substitution поискал, заменил /bin/sh на /bin/bash ошибка исчезла. И почему то не хотел в /tmp сами книги скидывать но там другая проблема, все работает большое вам спасибо! Буду постепенно вливатся.

censured
() автор топика
Ответ на: комментарий от censured

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

#!/bin/sh
URL="http://tululu.org/"
RAZDEL=fantastic
PAGE_TMP=/tmp/page.tmp 
BOOK_TMP=/tmp/book.tmp
BOOKS_DIR=/tmp/books
test -d $BOOKS_DIR || mkdir $BOOKS_DIR
for page in {1..10}
do
   echo -e "\
======================================\n\
Обрабатывается страница номер $page\n\
======================================"
   wget "${URL}/${RAZDEL}/$page" -O- 2> /dev/null | iconv -f cp1251 -t utf-8 -o $PAGE_TMP
   grep 'bookimage' $PAGE_TMP | while read BOOK 
   do
      echo $BOOK | sed s/alt.*//gi \
      | sed s/.*'><a '//gi \
      | sed s/'><img'//gi \
      | sed s/'\" '/'\"\n'/gi > $BOOK_TMP
      . $BOOK_TMP
      ID=`echo ${href//\/} | sed s/^b//`
      AUTOR="${title/ - *}"
      wget "${URL}/$href" -O-  2> /dev/null \
      | iconv -f cp1251 -t utf-8 \
      | grep 'скачать txt' > /dev/null && \
      echo " * Книга $title" ; \
      test -d "$BOOKS_DIR/$AUTOR" || mkdir "$BOOKS_DIR/$AUTOR"
      wget -c "${URL}/txt.php?id=${ID}" -O "$BOOKS_DIR/$AUTOR/${title/* - }.txt"  2> /dev/null
      wget -c "${URL}/shots/${ID}.jpg" -O "$BOOKS_DIR/$AUTOR/${title/* - }.jpg"  2> /dev/null
   done
done

Вот этой строкой:

AUTOR="${title/ - *}"
Из строки
$ echo $title
Брэдбери Рэй - Библиотека современной фантастики. Том 3. Рэй Брэдбери
срезается подстрока, в которой содержится имя автора:
$ echo ${title/ - *}
Брэдбери Рэй
А вот этой строкой срезается название книги:
$ echo ${title/* - }
Библиотека современной фантастики. Том 3. Рэй Брэдбери
С Именем автора проблем быть не должно, а вот с названием книги может быть, если в друг встретится строка вида «Имя Автора - Название - книги», то в этом случае будет срезана строка «книги», а не «Название - книги».

Поэтому вот эти строки можете изменить:

wget -c "${URL}/txt.php?id=${ID}" -O "$BOOKS_DIR/$AUTOR/${title/* - }.txt"  2> /dev/null
      wget -c "${URL}/shots/${ID}.jpg" -O "$BOOKS_DIR/$AUTOR/${title/* - }.jpg"  2> /dev/null
на
wget -c "${URL}/txt.php?id=${ID}" -O "$BOOKS_DIR/$AUTOR/${title}.txt"  2> /dev/null
      wget -c "${URL}/shots/${ID}.jpg" -O "$BOOKS_DIR/$AUTOR/${title}.jpg"  2> /dev/null
Но тут решайте сами или доработайте скрипт.

kostik87 ★★★★★
()
Ответ на: комментарий от censured

С самого начала я не мог понять как сделать переменную которая была бы от 1 до 10. Погуглив нашел то же самое что вы написали:

разумнее (в баше)

for (( j = 0; j < 10; j++ ))

И по прежнему не понятно как выхлоп for i in ... done передать на обработку следующей команде

ВНЕЗАПНО:

$ echo "XYZ"{1..5}"ABC"
XYZ1ABC XYZ2ABC XYZ3ABC XYZ4ABC XYZ5ABC
emulek
()
Ответ на: комментарий от kostik87

sed s/alt.*//gi | sed s/.*'><a '//gi | sed s/'><img'//gi | sed s/'\" '/'\«\n'/gi > $BOOK_TMP

Костик, зачем тебе столько команд sed?

sed "s/alt.*//gi;s/.*'><a '//gi;s/'><img'//gi;s/'\"'/'\"\n'/gi" > $BOOK_TMP
emulek
()
Ответ на: комментарий от kostik87

так будет работать, но надо понимать, чтоты там хотел сказать своими кавычками. А мне лень разгребать твою лапшу.

Просто поверь: запускать 10 процессов в конвейере — не лучшая идея.

emulek
()
Ответ на: комментарий от emulek

так будет работать, но надо понимать, чтоты там хотел сказать своими кавычками.

Мне проще написать так, а не задумываться о том, как переписать, что бы это работало в одну строку. Зачем ?

А мне лень разгребать твою лапшу.

Ну-ну, разгребай раз уж взялся тыкать в ошибки, а не хочешь тогда лучше помолчи.

Просто поверь: запускать 10 процессов в конвейере — не лучшая идея.

Я знаю, но здесь не 10, а 5. Кроме всего, так проще писать, на каждой строке отдельная операции выборки / срезки или чего-либо ещё, в общем отдельное регулярное выражение, не надо думать как его оптимизировать и читать проще.

UPD:
Ну и ты засветился:
www.linux.org.ru/people/drBatty/profile
www.linux.org.ru/people/emulek/profile
Зачем тебе два профиля ?

Подтверждение: http://postimg.org/image/plr5tfbm1/

kostik87 ★★★★★
()
Последнее исправление: kostik87 (всего исправлений: 1)
Ответ на: комментарий от kostik87

Мне проще написать так, а не задумываться о том, как переписать, что бы это работало в одну строку. Зачем ?

затем

sed "
s/alt.*//gi
s/.*'><a '//gi
s/'><img'//gi
s/'\"'/'\"\n'/gi
" > $BOOK_TMP
так нравится?

Ну-ну, разгребай раз уж взялся тыкать в ошибки, а не хочешь тогда лучше помолчи.

ну дык у тебя ошибка в том, что твой sed скрипт сначала bash парсит. Причём через страшную задницу: alt.* разбирается как ИМЯ ФАЙЛА под шаблон s/alt.*//gi у тебя такого файла нет, потому шаблон без изменений едет в sed. А если ЕСТЬ?

Т.е. ты написал скрипт, работа которого зависит от имён файлов в текущем каталоге.

Быдлокод с первой команды. Дальше даже не смотрел.

Я знаю, но здесь не 10, а 5. Кроме всего, так проще писать, на каждой строке отдельная операции выборки / срезки или чего-либо ещё, в общем отдельное регулярное выражение, не надо думать как его оптимизировать и читать проще.

Sed скрипт можно писать в любое количество строк, причём без всяких \.

Пиши на здоровье. Вызывать каждый раз sed для этого не только не нужно, но и вредно.

emulek
()
Ответ на: комментарий от emulek

ну дык у тебя ошибка в том, что твой sed скрипт сначала bash парсит. Причём через страшную задницу: alt.* разбирается как ИМЯ ФАЙЛА под шаблон s/alt.*//gi у тебя такого файла нет, потому шаблон без изменений едет в sed. А если ЕСТЬ?

Не разбирается, проверь в начале свои слова. Создай файлы с именами, подходящими под шаблон и выполни sed с регулярным выражением, которое якобы подходит под шаблон имени файла.

Т.е. ты написал скрипт, работа которого зависит от имён файлов в текущем каталоге.

Не зависит.

Быдлокод с первой команды. Дальше даже не смотрел.

Напиши свой вариант и выложи.

kostik87 ★★★★★
()
Ответ на: комментарий от emulek

А ты знаешь, что иметь несколько профилей запрещено правилами форума ? В итоге выбирай какой удалить, а какой оставить.

Cast: tazhate

kostik87 ★★★★★
()
Ответ на: комментарий от kostik87

Не разбирается, проверь в начале свои слова. Создай файлы с именами, подходящими под шаблон и выполни sed с регулярным выражением, которое якобы подходит под шаблон имени файла.

в данном случае не получится, ибо символ слеша невозможен в имени файла. За то ты будешь «обрадован» тем, как у тебя будут обрабатываться всякие { ! & и прочие такие символы.

Т.е. ты написал скрипт, работа которого зависит от имён файлов в текущем каталоге.

Не зависит.

в данной конкретной команде с данными конкретными условиями _может_ _быть_ не зависит.

Напиши свой вариант и выложи.

я тебе уже дал ссылку с кучей моих скриптов. Тебе мало?

emulek
()
Ответ на: комментарий от kostik87

А ты знаешь, что иметь несколько профилей запрещено правилами форума ?

нет не знаю. У меня один профиль, вот этот: www.linux.org.ru/people/emulek/profile

а при чём тут drBatty — мне неизвестно. Считай, что книжку про sed я написал в соавторстве с зелёной пони. Она для меня за шышками бегала. В благодарность я и отметил её в сём мануале. А потом её на ЛОРе забанили.

И при чём тут я?

emulek
()
Ответ на: комментарий от emulek

как у тебя будут обрабатываться всякие { ! & и прочие такие символы.

В данном случае у меня не используются указанные тобой символы. И если я буду их использовать то я позабочусь о их экранировании. В данном случае оно не нужно.

я тебе уже дал ссылку с кучей моих скриптов. Тебе мало?

Молодец, можешь повесить медаль на себя или на стену. Но я не вижу написанного тобой скрипта, решающего поставленную ТС задачу. К тому же соответствующему твоим требованиям.

kostik87 ★★★★★
()
Ответ на: комментарий от emulek

Ну в таком случае, как реинкарнации «зелёной пони», буде именно так я drbaty и называл в какой-то теме, ну а ты вряд ли перечитывал все темы и ответные наши сообщения, так что знать мог только drbaty, так что веди себя по спокойнее.

kostik87 ★★★★★
()
Ответ на: комментарий от kostik87

В данном случае у меня не используются указанные тобой символы. И если я буду их использовать то я позабочусь о их экранировании. В данном случае оно не нужно.

попробуй заэкранировать ! в интерактивном режиме. Да и { тоже заэкранировать непросто, если не использовать sed --regexp-extended, а использовать { хочется.

Молодец, можешь повесить медаль на себя или на стену. Но я не вижу написанного тобой скрипта, решающего поставленную ТС задачу. К тому же соответствующему твоим требованиям.

там было что-то похожее. Я уж и не помню.

так что знать мог только drbaty, так что веди себя по спокойнее.

возможно я лично знаю drBatty, тебе-то что с того?

emulek
()
Ответ на: комментарий от emulek

попробуй заэкранировать ! в интерактивном режиме. Да и { тоже заэкранировать непросто, если не использовать sed --regexp-extended, а использовать { хочется.

$ echo '!{'
!{
$ echo '!{' > /tmp/tst
$ sed s/\!// /tmp/tst 
{
$ sed s/\{// /tmp/tst 
!
$ sed s/'{'// /tmp/tst 
!
$ sed s/'!'// /tmp/tst 
{

там было что-то похожее. Я уж и не помню.

Пример?

возможно я лично знаю drBatty, тебе-то что с того?

Ничего, ну вот только не надо придумывать новые невероятные оправдания. Нет, ну поверить я, конечно могу, что drBatty будучи заблокированном в 0 часов 39 минут 20 секунд 19 августа 2013 года поехал к тебе, скажем в какой-нибудь пригород Санкт-Петербурга, а приехав, скажем где-то в пол 4-ого ночи того же числа, очень сильно расстроенным уговорил тебя зарегистрироваться на этом форуме.

Блокирован 19.08.2013 0:39:20, модератором beastie по причине: по результату голосования модераторов
И вот 19 августа 2013 года в 3 часа 37 минут 50 секунд на форуме создаётся новая учётная запись:
Дата регистрации: 19.08.2013 3:37:50
От имени человека, который написал руководство по sed, при чём в соавторстве drBatty, который бегал ему за шашлыками и в награду был удостоен упоминания, к тому же как уже ясно ты и drBatty лично знакомы, ну и знакомство это очень близкое, можно сказать дружеское, наверное, раз уж в столь поздний час drBatеy попросил тебя создать учётную запись на этом форуме.

Это всё присказка, а теперь сказка, ну не нужно выдумывать какие-то нелепые истории, оправдания, ну есть факт, что drBatty забанили 19.08.2013 в 0:39:20, а потом «кто-то» создал учётную запись в эту же ночь, позднее, а именно 19.08.2013 в 3:37:50, вероятность того, что это не только что заблокированный drBatty крайне мал, т.к. пользователь под новой учётно записью придумывает нелепые оправдания, после того, как показал сайт с информацией, которая указывает на то, что он и drBatty одно лицо.

В общем, хватит отпираться тема закрыта.

Забанили тебя, создал новую учётку, хорошо, следуй правилам форума и нормам общения и всё будет хорошо.

kostik87 ★★★★★
()
Ответ на: комментарий от kostik87

Всё гораздо проще:

эх... Вот я с самого начала кавычки рекомендовал юзать. Ты разве не понял что-ли?

emulek
()
Ответ на: комментарий от emulek

emulek, а через точку с запятой записывать команды седа - это тоже самое что и с ключом -е:

sed -e 1d -e 'command1' -e 'command1' -e 'command1' file1 > file2

nerve ★★
()
Ответ на: комментарий от nerve

а через точку с запятой записывать команды седа - это тоже самое что и с ключом -е:

AFAIK да.

ключ нужен что-бы записывать такое:

$ echo "test test test..." | sed -e 'a abc' -e 'a xyz'
test test test...
abc
xyz
иначе такое одностроком не записать (команда a жрёт всё до конца строки)

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.