Так ось: першим ділом треба було зясувати загальну кількість виконавців викладених на сайті. Відкривши вкладку виконавці на сайті я побачив 4 сторінки виконавців. Передивившись декілька посилань на сторінки виконавців було ясно що виконавців десь в районі 1000. На сайті вони розміщені по алфавітному зростанню. В випадку парсингу ID виконавців були б розміщені хаотично. Тому я вирішив грабити по зростанні ID кожного виконавця.Написав простий скрипт:
#!/bin/bash for id in `seq 1 1200`; do GET "http://nashe.com.ua/artist.htm?id=$id" > ./artists/$id.html check=`cat "./artists/$id.html" | grep arttitle | cut -d"'" -f4` if [ "$check" = "arttitle" ]; then echo $id >> artist-list echo "id=$id is ok!" else rm -rf ./artists/$id.html echo "id=$id error..." fi done
який перевіряє ID від 1 до 1200 на наявність виконавця. Коли перевірка дійшла до 1000 скрипт почав видавати постійні "error..". Стало ясно що виконавців 953, а не 722 як пише на сайті.
Коли в параметрі id викликано неправильне значення то скрипт повертає усіх виконавців. За допомогою простого парсингу можна відрізнити яка сторінка видана: з існуючим ID чи неправильним.
flashbag@laptop:~/nashe.com.ua$ GET http://nashe.com.ua/artist2.htm?page=2 | grep arttitle flashbag@laptop:~/nashe.com.ua$ GET http://nashe.com.ua/artist.htm?id=492 | grep arttitle <div align='left' class='arttitle' style='width: 45%;'>K402</div> flashbag@laptop:~/nashe.com.ua$ GET http://nashe.com.ua/artist.htm?id=492 | grep arttitle | cut -d"'" -f4 arttitle
Для виконавця в коді присутній блок div з класом arttitle. Якщо в команду ще добавити контейнер cut можна чітко виділити ключове слово
Звідси можна записати назву кожного виконавця в файл з такою послідовністю як вони розміщені у базі даних: від id=1 до 953. Ось скрипт get-artists.sh:
#!/bin/bash rm -rf artist-names touch artist-names for id in `seq 1 953`; do cat ./artists/${id}.html | grep arttitle | cut -d'>' -f2 | cut -d'<' -f1 >> artist-names done
Це навіть смішно скриптом назвати, можна цей код в одну команду втиснути )))
Тепер я вирішив дістати усі стилі виконавців, код:
#!/bin/bash rm -rf styles.list touch styles.list for id in `seq 1 953`; do a=`cat "./artists/$id.html" | grep "<br><span class='title'>"` b=`echo ${a//*<span} | cut -d'>' -f3 | cut -d'<' -f1` echo $id $b echo $b >> styles.list doneпісля цього рядка
a=`cat "./artists/$id.html" | grep "<br><span class='title'>"`змінна а набувала різного значення, у виконавців про яких була повна інформація змінна а приймала цю інформацію, а у тих в кого був лише стиль - приймала значення лише стилю.
Іншими словами змінна а приймала значеня html-кода блока про виконавця. Треба було якось виділити її і я побачив що усі пункти ( Дискографія, Оф.сайт, Email ) крім стилю були розміщені в тегах div. За допомогою цієї команди
echo ${a//*<span}можна виділити всю інфу після тега span. А далі cut-ом виділяється тільки потрібне значення стилю/стилів
Файл styles.list має відповідно 953 рядка і у кожному є стиль/стилі виконавця або нема стилю. Є і такі виконавці як 98,100,109,153,154,155 та інші.
Тепер в мене виникла ідейка виділити кожний унікальний стиль. Алгоритм скрипту зразу проскочив в голові: порожні рядки видаляються, в того виконавця в кого два або більше стилів, стилі розділяються, кожному стилю - окремий рядок, далі записуються в окремий файл один унікальний стиль тільки один раз. Для перевірки схожості стилів треба видаляти лишні пробіли в рядках.
Розписувати створення скрипту не буду, бо це буде довго і нудно, ось готовий скрипт:
#!/bin/bash -x file="style-by-line"; rm -rf $file touch $file cat styles.list | while read line; do if [ "$line" != "" ]; then x=${line//[!,]/} if [ "${#x}" = "0" ]; then echo $line | tr -s " " | sed 's/^[ ]//g' >> $file fi if [ "${#x}" = "1" ]; then echo $line | cut -d',' -f1 | tr -s " " | sed 's/^[ ]//g' >> $file echo $line | cut -d',' -f2 | tr -s " " | sed 's/^[ ]//g' >> $file fi if [ "${#x}" = "2" ]; then echo $line | cut -d',' -f1 | tr -s " " | sed 's/^[ ]//g'>> $file echo $line | cut -d',' -f2 | tr -s " " | sed 's/^[ ]//g'>> $file echo $line | cut -d',' -f3 | tr -s " " | sed 's/^[ ]//g'>> $file fi if [ "${#x}" = "3" ]; then echo $line | cut -d',' -f1 | tr -s " " | sed 's/^[ ]//g'>> $file echo $line | cut -d',' -f2 | tr -s " " | sed 's/^[ ]//g'>> $file echo $line | cut -d',' -f3 | tr -s " " | sed 's/^[ ]//g'>> $file echo $line | cut -d',' -f4 | tr -s " " | sed 's/^[ ]//g'>> $file fi fi done sort -k 1,1 -u style-by-line > uniq-styles
Зразу в очі кидається ондоманітні умови. Так це лишнє, але з циклами в цьому напрямку в мене поки що не дуже. Змінна x - це кількість ком в одному рядку. Експерементальний шляхом визначено - максимальне значення змінної x=3, три коми-розділювачі, отже максимально можливо 4 стилі для виконавця.
Остання команда мене просто вражає. Я стільки гуглив щоб зробити унікальне сортування кожного рядка в файлі. Вже надумав написате це сортування на PHP, але в останній момент найшов найоптимальніше рішення - унікальне сортування однією командою.
Так ось вийшло 37 унікальних стилів. Відсортовані по алфавіту в OpenOffice. Ось вони:
А капелла Альтернатива Альтернативний рок Брутал-поп Вільний український метал Готик-фольк метал Гранж Джерело: Ейсід-хоп Електро Електро-рок Електро-фолк Етно-арт-рок Етно-ска-панк Етно-хаус Інді-ретро-поп Латино Ліричний рок Нео-психоделія Нью-ейдж Нью-метал Подільський фундаментал Поп-рок Ритм-н-блюз Ритуальний фолк Рок Рок-н-рол Рокабіллі Симфо-арт-метал Техно-денс Фолк Фолк-дарк-метал Фолк-метал Фолк-рок Фолк-фанк-рок Хіп-хоп Християнський рок
Тут і найшовся перший баг: стиль "Джерело:" ( виділений жирним ). Коли я подивився в усі стилі то цей стиль належав виконавцю з id=452. Сторінка цього виконавця справді не така як усі, в середині тегу span там знаходиться посилання на джерело інформації. Значить скрипт без багів, це мене порадувало =)
Щоб це все не здавалсь маячнею, я написав прості скрипти index.php та show.php.
Лістинг index.php:
<form action=show.php method=get> <select name=style> <?php $uniq_styles=file('uniq-styles'); for ($i=0; $i<count($uniq_styles); $i++ ) { echo '<option name='.$i.'>'.$uniq_styles[$i].'</option><br>'; } ?> </select> <input type='submit' value="OK"> </form>
Лістинг show.php:
<?php $style=$_GET['style']; echo '<b>'.$style.'</b><br>'; $styles=file("styles.list"); $artists=file("artist-names"); for ($i=1; $i<count($styles); $i++ ) { if (substr_count($styles[$i-1], $style)>0) echo '<a target=_blank href="http://nashe.com.ua/artist.htm?id='.$i.'">'.$artists[$i-1].'<br>'; } ?>
Тут можна їх потестувати http://kepnung.host-ua.org.ua/nashe.com.ua
Цим скриптам потрібні файли uniq-styles, styles.list, artists-names.
Тепер все спочатку, коротко і ясно:
- Щоб не закачувати кожен раз для парсингу всі сторінки виконавців є скрипт download-artists.sh. Він закачує усі 953 сторінки у папку artists, у вигляді ${id}.html.
- Щоб записати в файл artist-names назву кожного виконавця є скрипт get-artists.sh
- Щоб дістати стиль/стилі кожного виконавця в файл styles.list є скрипт get-styles.sh
- І нарешті щоб виділи тільки унікальні стилі в файл uniq-styles є скрипт get-uniq-styles.sh
Наочний приклад цього грабингу це посилання вище. Іншими словами - це фільтр виконавців по стилю, на сайті такої штучки нема. Треба підказати їм таку ідейку.

Немає коментарів:
Дописати коментар