Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

На самом деле это единственный раздел про unix на этом форуме

Модератор: /dev/random

Аватара пользователя
nerve
Сообщения: 273
ОС: OpenBSD

Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение nerve » 16.06.2014 14:46

Есть старый архив форума, созданный какой-то качалкой. Состоит из index.htm и множества файлов и папок.
Из всего этого безобразия хотелось бы вытянуть посты по маске пользователя в один файл и имена файлов где встречается такой пользователь в другой файл.
под спойлером кусок кода из файла с которым нужно работать. в самом файле естественно куча другого "мусора", который надо игнорить.
Spoiler

Код: Выделить всё

<!--Begin Msg Number 47270-->
<table class='ipbtable' cellspacing="0">
	<tr>
		<td valign="middle" class="post_head" width="1%">
			<a name="entry47270"></a>

				<div id="post-member-47270" class='popmenubutton-new-out'>
					<span class="normalname">
	<img src='style_images/pro1193739588/folder_profile_portal/user-offline.png' alt='' border='0' /><a href='http://www.domain.com/ipb/index.php?showuser=3408'>USER_NAME</a></span>
				</div>
				<!-- member menu -->
				<div class='popupmenu-new' id='post-member-47270_menu' style='display:none;width:230px'>
					<div class='popupmenu-item-last'>

						<div style='float:right'>
							<div class='pp-image-thumb-wrap'>
								<img src='style_images/pro1193739588/folder_profile_portal/pp-blank-thumb.png' width='50' height='50' alt='' />
							</div>

								<div style='margin-top:5px;margin-left:6px;'>
									<img src="style_images/pro1193739588/rating_0_mini.gif" alt='Рейтинг: 0' style='vertical-align:middle' border='0' />
								</div>

						</div>
						<div class='popupmenu-item'>

	<img src='style_images/pro1193739588/folder_profile_portal/gender_mystery.png' id='pp-entry-gender-img-3408' alt='' border='0' />
 <a href="http://www.domain.com/ipb/index.php?showuser=3408">Просмотр профиля</a>
						</div>

							<div class='popupmenu-item'>

									<img src='style_images/pro1193739588/folder_profile_portal/friend_add_small.png' alt='' border='0' /> <a href="#" onclick='friends_pop("&do=add&member_id=3408&md5check=f43a44465092388bc3bf2a3c37128507"); return false'>Добавить в друзья</a>

							</div>
							<div class='popupmenu-item'>
								<img src='style_images/pro1193739588/folder_profile_portal/send_pm_small.png' alt='' border='0' /> <a href="http://www.domain.com/ipb/index.php?act=Msg&CODE=4&MID=3408">Отправить сообщение</a>
							</div>
							<div class='popupmenu-item'>
								<img src='style_images/pro1193739588/folder_profile_portal/find_posts.png' alt='' border='0' /> <a href='http://www.domain.com/ipb/index.php?act=Search&CODE=gettopicsuser&mid=3408'>Найти темы пользователя </a>
							</div>
							<div class='popupmenu-item-last'>
								<img src='style_images/pro1193739588/folder_profile_portal/find_posts.png' alt='' border='0' /> <a href='http://www.domain.com/ipb/index.php?act=Search&CODE=getalluser&mid=3408'>Найти сообщения пользователя</a>
							</div>

					</div>
				</div>
				<!-- member menu -->
				<script type="text/javascript">
					ipsmenu.register( "post-member-47270", '', 'popmenubutton-new', 'popmenubutton-new-out' );
				</script>


		</td>
		<td class="post_head" valign="middle" width="99%">
			<!-- POSTED DATE DIV -->
			<div style="float: left;">
				<span class="postdetails"> <img src='style_images/pro1193739588/to_post_off.gif' alt='сообщение' border='0' style='padding-bottom:2px' /> 12.4.2006, 12:27</span>
			</div>
			<!-- REPORT / DELETE / EDIT / QUOTE DIV -->
			<div align="right">
				<span class="postdetails"> Сообщение
					<a title="Ссылка на это сообщение" href="http://www.domain.com/ipb/index.php?showtopic=2775&view=findpost&p=47270" onclick="link_to_post(47270); return false;">#1</a>

				</span>
			</div>
		</td>
	</tr>
	<tr>
		<td valign="top" class="post2 post_left">
        	<span class="postdetails">

        			<br /><br />

        		Гость<br />
        		<img src='style_images/pro1193739588/pip.gif' border='0'  alt='*' /><br /><br />
        		Группа: <span style='color:green'>Пользователи</span><br />
        		Сообщений: 35<br />
        		Регистрация: 18.1.2006<br />
        		Из: spb.ru<br />
        		Пользователь №: 3.408<br />

				<br />

        	</span><br />
        	<img src="style_images/pro1193739588/spacer.gif" alt="" width="160" height="1" /><br />
       </td>
       <td width="100%" valign="top" class="post2" id='post-main-47270'>
			<!-- THE POST 47270 -->
			<div class="postcolor" id='post-47270'>
				ну что, касманафты, с праздником )))<br /><br /><a href="http://chipigik.weles.ru/postcards/12aprelya.swf" target="_blank">http://chipigik.weles.ru/postcards/12aprelya.swf</a>


				<!--IBF.ATTACHMENT_47270-->
			</div>


			<!-- THE POST -->
		</td>
	</tr>
	<tr>
		<td class="formbuttonrow" nowrap="nowrap">
			<div style='text-align:left'><a href="java script:scroll(0,0);"><img src='style_images/pro1193739588/p_up.gif' border='0'  alt='Перейти в начало страницы' /></a><a href="http://www.domain.com/ipb/index.php?act=report&t=2775&p=47270&st=0"><img src='style_images/pro1193739588/p_report.gif' border='0'  alt='Сообщить о сообщении' /></a></div>
		</td>
		<td class="formbuttonrow" nowrap="nowrap">
			<!-- PM / EMAIL / WWW / MSGR -->
			<div style="float: left;">
				 
			</div>
			<!-- REPORT / UP -->
         	<div align="right">
         		<a href="#" onclick="multiquote_add(47270); return false;" title="Добавить к многочисленным цитатам"><img src="style_images/pro1193739588/p_mq_add.gif" name="mad_47270" alt="+" /></a><a href="http://www.domain.com/ipb/index.php?act=Post&CODE=02&f=8&t=2775&qpid=47270" title="Ответить прямо в этом сообщении"><img src='style_images/pro1193739588/p_quote.gif' border='0'  alt='Цитировать сообщение' /></a>
         	</div>
         </td>
	</tr><tr>
	<td class="catend" colspan="2">
	<!-- no content -->
	</td>
</tr>
</table>
<!--Begin Msg Number 47273-->


как видно блок сообщения находится между тегами
<!--Begin Msg Number 47270-->
и
<!-- no content -->

имя юзера или его ID находятся в такой строке:

Код: Выделить всё

<img src='style_images/pro1193739588/folder_profile_portal/user-offline.png' alt='' border='0' /><a href='http://www.domain.com/ipb/index.php?showuser=3408'>USER_NAME</a></span>


само сообщение находится между такими тегами

Код: Выделить всё

<!-- THE POST 47270 -->
			<div class="postcolor" id='post-47270'>
				ну что, касманафты, с праздником )))<br /><br /><a href="http://chipigik.weles.ru/postcards/12aprelya.swf" target="_blank">http://chipigik.weles.ru/postcards/12aprelya.swf</a>


				<!--IBF.ATTACHMENT_47270-->
			</div>


			<!-- THE POST -->

то есть надо рекурсивно обойти все *.htm файлы, искать в них Юзера по маске (имя или ИД), находить границы сообщения этого юзера, вытягивать оттуда текст самого сообщения между тегами THE POST и добавлять этот текст в отдельный файл.
для обработки каждого файла насколько я понимаю должен быть отдельный цикл, ведь может быть несколько сообщений.

Код: Выделить всё

#!/bin/bash
LIST=$(find . -type f -name "*.htm")
for f in $LIST; do
echo "$f"
done

находим файлы которые надо в дальнейшем обрабатывать
$ for f in $LIST; do echo "$f"; done | head -4
./index.htm
./ipb/index.php.act=attach&code=showtopic&tid=6064.htm
./ipb/index.php.showtopic=1186.htm
./ipb/index.php.act=attach&code=showtopic&tid=3551.htm
Спасибо сказали:

Аватара пользователя
Hephaestus
Сообщения: 2669
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение Hephaestus » 17.06.2014 09:17

Думаю, что sed, awk и grep могут спасти гиганта мысли. Также не забываем про pipe.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:

Аватара пользователя
tmp13
Сообщения: 986
ОС: openSuse 11.2

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение tmp13 » 17.06.2014 13:55

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

ну вторая часть решается просто=)

Код: Выделить всё

grep -i -R -l USER_NAME --include '*.htm' .


Красных бей и белых бей!
Вот вам иерархия!
Я люблю тебя за это, милая моя,
Разудалая, хмельная мать моя – Анархия!
Спасибо сказали:

Аватара пользователя
tmp13
Сообщения: 986
ОС: openSuse 11.2

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение tmp13 » 17.06.2014 17:06

Ну и опять же от делать нех небольшой изврат по пункту 1

Код: Выделить всё

#!/bin/bash
FIND_FILENAME="line_test.txt"
FILENAME=$FIND_FILENAME"_forsed"
cp $FIND_FILENAME $FILENAME
USERNAME="USER_NAME"
count=`grep USER_NAME line_test.txt|wc -l`
c=0
while [ $c -lt $count ]; do
        startline=`grep -n $USERNAME $FILENAME|awk -F':' '{print $1}'|head -1`
        endpost_s=`tail -n +$startline $FILENAME | grep -n '<!-- THE POST -->'|awk -F':' '{print $1}'|head -1`
        startpost_s=`tail -n +$startline $FILENAME | grep '<!-- THE POST.*[0-9]\{1\}.*-->' -n|head -1|awk -F':' '{print $1}'`
        epos=$((startpost_s+startline))
        spos=$((endpost_s-startpost_s-1))
        countdel=$((startline+endpost_s))
        cat $FILENAME |tail -n +$epos|head -$spos
        sed -i '1,'$countdel'd' $FILENAME
        ((c++))
done
exit 0


Если всё это дело обернуть в функцию запилить ей передачу списка файлов и т.д... то всё будет ок поидее должна возарвщать чёт типа:

<div class="postcolor" id='post-47270'>
ну что, касманафты, с праздником )))<br /><br /><a href="http://chipigik.weles.ru/postcards/12aprelya.swf" target="_blank">http://chipigik.weles.ru/postcards/12aprelya.swf</a>


<!--IBF.ATTACHMENT_47270-->
</div>


<div class="postcolor" id='post-47270'>
Part two=) ну что, касманафты, с праздником )))<br /><br /><a href="http://chipigik.weles.ru/postcards/12aprelya.swf" target="_blank">http://chipigik.weles.ru/postcards/12aprelya.swf</a>


<!--IBF.ATTACHMENT_47270-->
</div>


Если будет надо вкраце распишу эту сумасшедшую логику=)
Красных бей и белых бей!
Вот вам иерархия!
Я люблю тебя за это, милая моя,
Разудалая, хмельная мать моя – Анархия!
Спасибо сказали:

Аватара пользователя
nerve
Сообщения: 273
ОС: OpenBSD

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение nerve » 17.06.2014 19:00

tmp13 писал(а):
17.06.2014 17:06
Если всё это дело обернуть в функцию запилить ей передачу списка файлов и т.д... то всё будет ок


Код: Выделить всё

#!/bin/bash
function ()
{
FIND_FILENAME=$1
FILENAME=$FIND_FILENAME"_forsed"
cp $FIND_FILENAME $FILENAME
USERNAME="USER_NAME"
count=`grep USER_NAME line_test.txt|wc -l`
c=0
while [ $c -lt $count ]; do
        startline=`grep -n $USERNAME $FILENAME|awk -F':' '{print $1}'|head -1`
        endpost_s=`tail -n +$startline $FILENAME | grep -n '<!-- THE POST -->'|awk -F':' '{print $1}'|head -1`
        startpost_s=`tail -n +$startline $FILENAME | grep '<!-- THE POST.*[0-9]\{1\}.*-->' -n|head -1|awk -F':' '{print $1}'`
        epos=$((startpost_s+startline))
        spos=$((endpost_s-startpost_s-1))
        countdel=$((startline+endpost_s))
        cat $FILENAME |tail -n +$epos|head -$spos
        sed -i '1,'$countdel'd' $FILENAME
        ((c++))
done
}

LIST=$(find . -type f -name "*.htm")
for f in $LIST; do
function f
done

находим файлы и в цикле каждый файл передаем твоей функции. сама функция берет имя файла как параметр $1.
правильно?
если расскажешь логику своей функции будет здорово.



Спасибо сказали:

Аватара пользователя
SLEDopit
Модератор
Сообщения: 4679
Статус: фанат консоли (=
ОС: GNU/Debian, RHEL

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение SLEDopit » 17.06.2014 20:07

tmp13 писал(а):
17.06.2014 17:06
Ну и опять же от делать нех небольшой изврат по пункту 1
Можно немного короче ( и работать будет существенно быстрее ):

Код: Выделить всё

sed -n '/>USER_NAME</{p;:a;/THE POST/!{n;ba;};/THE POST/{:b;/\n.*THE POST/!{N;bb};p};}' filename



зы. раз уж сделал сложную часть, то полностью это будет выглядеть так:

Код: Выделить всё

find . -type f -name "*html" -exec grep -q USER_NAME {} \; -exec ~/s.sh {} \;

где s.sh выглядит так:

Код: Выделить всё

#!/bin/bash
sed -n '/>USER_NAME</{p;:a;/THE POST/!{n;ba;};/THE POST/{:b;/\n.*THE POST/!{N;bb};p};}' "$1" > "${1}.cleaned.html"


суть работы: ищутся все html файлы в текущей директории, где упоминается имя пользователя. потом из таких файлов выдираются нужные вещи и аккуратно складываются в filename.cleaned.html . собственно всё просто.
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
Спасибо сказали:

Аватара пользователя
nerve
Сообщения: 273
ОС: OpenBSD

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение nerve » 18.06.2014 11:44

гениально!
Следопыт, объясни пожалуйста для далеких как работает твой сед скрипт. читал-читал описания команд, но все равно не понял как они в данном случае применяются.
и можно ли сделать так, чтоб cleaned файлы складывались в одну определенную директорию без переименования исходного файла?
Спасибо сказали:

Аватара пользователя
SLEDopit
Модератор
Сообщения: 4679
Статус: фанат консоли (=
ОС: GNU/Debian, RHEL

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение SLEDopit » 18.06.2014 12:13

nerve писал(а):
18.06.2014 11:44
Следопыт, объясни пожалуйста для далеких как работает твой сед скрипт.
SLEDopit писал(а):
17.06.2014 20:07
sed -n '/>USER_NAME</{p;:a;/THE POST/!{n;ba;};/THE POST/{:b;/\n.*THE POST/!{N;bb};p};}' filename
-n -- не выводить ничего. только то, что принудительно попросят.
/>USER_NAME</ -- ищем строку с именем пользователя и как только нашли, начинаем применять набор команд в {}
p -- вывести строку с именем пользователя
:a;/THE POST/!{n;ba;} -- цикл. пропустить все строки от строки с USER_NAME до строки с THE POST
/THE POST/{:b;/\n.*THE POST/!{N;bb};p} -- ещё один цикл запускается на строке с THE POST и складывает все строки до следующего THE POST в буфер. как только натыкается на второй THE POST выводит всё содержимое буфера и начинает всё сначала.

так понятно или нужно ещё подробнее?

зы. для лучше понимания, стоит помнить, что sed работает с файлом построчно. т.е. считывает строку и пытается применить все эти правила. но в случае цикла и команд n/N считывание следующей строки происходит принудительно.

nerve писал(а):
18.06.2014 11:44
и можно ли сделать так, чтоб cleaned файлы складывались в одну определенную директорию без переименования исходного файла?
можно. для этого нужно вот это

Код: Выделить всё

"$1" > "${1}.cleaned.html"

поменять на это:

Код: Выделить всё

"$1" > /path/to/dir/"${1##*/}.cleaned.html"
## ${1##*/} -- если имя файл заодно содержит и какие-то директории, они отрежутся с помощью ##*/
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
Спасибо сказали:

Аватара пользователя
nerve
Сообщения: 273
ОС: OpenBSD

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение nerve » 18.06.2014 13:53

SLEDopit писал(а):
18.06.2014 12:13
для этого нужно вот это

Код: Выделить всё

"$1" > "${1}.cleaned.html"

поменять на это:

Код: Выделить всё

"$1" > /path/to/dir/"${1##*/}.cleaned.html"
## ${1##*/} -- если имя файл заодно содержит и какие-то директории, они отрежутся с помощью ##*/

$ ls | grep 5500
index.php.showtopic=5500.htm
index.php.showtopic=5500.htm.cleaned.html

сейчас cleaned.html файлы появляются рядом с оригинальными файлами во всех каталогах, где найдено совпадение с USER_NAME.
если складывать все найденные файлы в отдельную директорию, то .cleaned.html можно опустить.
то есть делать так:

Код: Выделить всё

"$1" > /path/to/dir/"${1##*/}"

можешь ткнуть носом в руководство, где описывается вот этот момент: "${1##*/}".
можно ли таким методом отрезать имя получаемого файла таким образом, чтоб на выходе получалось ID_темы.htm
$ ls -1 | grep htm | tail
index.php.showtopic=980&st=30.htm
index.php.showtopic=980&st=30.htm.cleaned.html
index.php.showtopic=980&st=60.htm
index.php.showtopic=980&st=60.htm.cleaned.html
index.php.showtopic=995.htm
index.php.showtopic=998.htm
index.php.showtopic=998&st=120.htm
index.php.showtopic=998&st=30.htm
index.php.showtopic=998&st=60.htm

то есть если тема на нескольких страниц тогда
980&st=30.htm
980&st=60.htm
если на одной, тогда
995.htm
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение drBatty » 18.06.2014 14:57

nerve писал(а):
18.06.2014 13:53
можешь ткнуть носом в руководство, где описывается вот этот момент: "${1##*/}".

# ищет и отрезает до первого символа с начала
% ищет и отрезает до первого символа с конца
## до последнего с начала
%% тоже до последнего но с конца.

Т.е. ${1##*/} находит последний "/" с начала строки

$

$ echo ${V} 1/2/3/4 $ echo ${V#*/} 2/3/4 $ echo ${V##*/} 4 $ echo ${V%/*} 1/2/3 $ echo ${V%%/*} 1



nerve писал(а):
18.06.2014 13:53
можно ли таким методом отрезать имя получаемого файла таким образом, чтоб на выходе получалось ID_темы.htm

можно. Но есть команда basename.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение drBatty » 18.06.2014 15:03

nerve писал(а):
18.06.2014 13:53
index.php.showtopic=980&st=30.htm.cleaned.html

так наверное:

$

$ echo $V index.php.showtopic=980&st=30.htm.cleaned.html $ echo ${V##*=} 30.htm.cleaned.html


на sed

$

$ echo $V | sed 's/.*=//' 30.htm.cleaned.html


да, grep тут не нужен.

фильтрацию можно организовать например так:

$

$ echo $V | sed '/htm/!d;s/.*=//' 30.htm.cleaned.html



а на bash так:

Код: Выделить всё

if [ "$V" != "${V/htm//}" ]; then
  # в строке есть htm
fi
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

Аватара пользователя
nerve
Сообщения: 273
ОС: OpenBSD

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение nerve » 18.06.2014 15:12

drBatty писал(а):
18.06.2014 14:57
Т.е. ${1##*/} находит последний "/" с начала строки

поучительно, спасибо.
Спасибо сказали:

Аватара пользователя
SLEDopit
Модератор
Сообщения: 4679
Статус: фанат консоли (=
ОС: GNU/Debian, RHEL

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение SLEDopit » 18.06.2014 15:34

nerve писал(а):
18.06.2014 13:53
можешь ткнуть носом в руководство, где описывается вот этот момент: "${1##*/}".
тыц
drBatty писал(а):
18.06.2014 15:03
echo ${V##*=}
это не совсем то. тут нужно отрезать до первого =. иначе файлы будут перезатирать друг друга ( тем с несколько страницами может быть много ).
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
Спасибо сказали:

Аватара пользователя
nerve
Сообщения: 273
ОС: OpenBSD

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение nerve » 18.06.2014 17:02

немного подкорректировал для своего случая
$ find . -type f -name "*php.showtopic*.htm" -exec grep -q USERNAME {} \; -exec ./s.sh {} \;

Код: Выделить всё

#!/bin/bash
sed -n '/>USERNAME</{p;:a;/THE POST/!{n;ba;};/THE POST/{:b;/\n.*THE POST/!{N;bb};p};}' "$1" > /home/USERNAME/"${1#*=}"

пошуршало несколько минут диском и выдало такой результат

user@host

$ ls -1 | wc -l 763 $ ls -1 | head 1024.htm 1117.htm 1117&st=30.htm 1119.htm 1123.htm 1123&st=30.htm 1149.htm 1154&st=30.htm 1154&st=60.htm 1154&st=90.htm



Спасибо сказали:

Аватара пользователя
nerve
Сообщения: 273
ОС: OpenBSD

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение nerve » 19.06.2014 13:23

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

Код: Выделить всё

mysql> describe ibf_posts;
+------------------+------------------+------+-----+---------+----------------+
| Field            | Type             | Null | Key | Default | Extra          |
+------------------+------------------+------+-----+---------+----------------+
| pid              | int(10)          | NO   | PRI | NULL    | auto_increment |
| append_edit      | tinyint(1)       | YES  |     | 0       |                |
| edit_time        | int(10)          | YES  |     | NULL    |                |
| author_id        | mediumint(8)     | NO   | MUL | 0       |                |
| author_name      | varchar(255)     | YES  |     | NULL    |                |
| use_sig          | tinyint(1)       | NO   |     | 0       |                |
| use_emo          | tinyint(1)       | NO   |     | 0       |                |
| ip_address       | varchar(46)      | NO   | MUL | NULL    |                |
| post_date        | int(10)          | YES  | MUL | NULL    |                |
| icon_id          | smallint(3)      | YES  |     | NULL    |                |
| post             | mediumtext       | YES  | MUL | NULL    |                |
| queued           | tinyint(1)       | NO   | MUL | 0       |                |
| topic_id         | int(10)          | NO   | MUL | 0       |                |
| post_title       | varchar(255)     | YES  |     | NULL    |                |
| new_topic        | tinyint(1)       | YES  |     | 0       |                |
| edit_name        | varchar(255)     | YES  |     | NULL    |                |
| has_modcomment   | tinyint(1)       | YES  |     | 0       |                |
| post_key         | varchar(32)      | NO   | MUL | 0       |                |
| post_htmlstate   | smallint(1)      | NO   |     | 0       |                |
| post_edit_reason | varchar(255)     | NO   |     |         |                |
| post_thanks      | text             | YES  |     | NULL    |                |
| private_data     | text             | YES  |     | NULL    |                |
| post_bwoptions   | int(10) unsigned | NO   |     | 0       |                |
| pdelete_time     | int(11)          | NO   |     | 0       |                |
| post_field_int   | int(10)          | NO   |     | 0       |                |
| post_field_t1    | text             | YES  |     | NULL    |                |
| post_field_t2    | text             | YES  |     | NULL    |                |
+------------------+------------------+------+-----+---------+----------------+

pid соответствует номеру отсюда <!--Begin Msg Number 47270-->. и находится еще в нескольких местах внутри поста
author_name известен и пусть будет равен USER_NAME.
post_date находится в этом блоке:

Код: Выделить всё

<!-- POSTED DATE DIV -->
<div style="float: left;">
<span class="postdetails"> <img src='style_images/pro1193739588/to_post_off.gif' alt='сообщение' border='0' style='padding-bottom:2px' /> 12.4.2006, 12:27</span>
</div>

post находится в этом блоке между тегами div.

Код: Выделить всё

<!-- THE POST 47270 -->
<div class="postcolor" id='post-47270'>
ну что, касманафты, с праздником )))<br /><br /><a href="http://chipigik.weles.ru/postcards/12aprelya.swf" target="_blank">http://chipigik.weles.ru/postcards/12aprelya.swf</a>


<!--IBF.ATTACHMENT_47270-->
</div>
<!-- THE POST -->

topic_id равен цифрам в имени файла. это всегда цифры между первым равно и любым другим символом: 5500, 980 и тп.
index.php.showtopic=5500.htm
index.php.showtopic=980&st=30.htm

Shell

$ echo "index.php.showtopic=5500.htm" | sed 's/.*=\([0-9]*\).*/\1/' 5500


то есть нужно:
- брать каждый файл в котором нашелся USER_NAME
- присваивать переменной topic_id значение из имени этого файла
- присваивать переменной pid значение, соответствующее post_id из границ поста между <!--Begin Msg Number 47270--> и <!-- no content -->
- присваивать переменной post_date дату сконвертированную в секунды
конвертация даты была подсказана товарищем /dev/random в соседней теме:

Shell

$ date +%s -d "$(echo '12.4.2006, 12:27' | sed 's/\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\),/\3-\2-\1/')" 1144837620


- присваивать переменной post сам текст
- остальные значения для занесения в базу статические
- передать это все конвеером или как-то еще в БД

Shell

$ echo "INSERT INTO ifb_posts (pid,post_date,post,topic_id) VALUES ('$pid', '$post_date', '$post','$topic_id');" | mysql -pPassword db_name


- если в файле есть еще один пост с USER_NAME то обрабатывать его
- иначе переходить к другому файлу.

upd. не подумал, перед внесением данных в таблицу постов надо проверять есть ли topic_id в tid в таблице тем ibf_topics. если такая тема есть - заносить, если нет - то все данные такого поста записывать отдельно.

Shell

$ cat s.sh ##!/bin/bash set -e USER="TTT" post_amount=`grep "$USER" "$1" | wc -l` count=0 if [ "$post_amount" -eq "0" ]; then exit 0 fi topic_id=`echo $1 | sed 's/.*showtopic=\([0-9]\+\).*/\1/'` echo "topic_id=$topic_id" while [ $count -lt $post_amount ] do post_id=`grep -B2 -m1 "$USER" "$1" | sed -n '1p' | sed 's/^.*member-\([0-9]*\).*$/\1/'` echo "post_id=$post_id" post_date=`date +%s -d "$(grep -A49 -m1 "$USER" "$1" | tail -1 | sed 's/^.*\/> \([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\), \([0-9]\+:[0-9]\+\).*/\3-\2-\1 \4/')"` echo "date=$post_date" post_text=`grep -A85 -m1 "$USER" "$1" | tail -4 | sed 's/^[ \t]*//'` #echo "text=$post_text" # if [ $(mysql -N -s -pPassword -e \ # "use db_name; SELECT count(*) FROM ibf_topics WHERE tid=$topic_id;") -eq 1 ]; then # echo "INSERT IGNORE INTO ifb_posts (pid,author_id,author_name,use_sig,use_emo,ip_address,post_date,post,topic_id) VALUES \ # ('$post_id', '3037', 'Soma', '1', '1', '194.44.167.228', '$post_date', '$post_text','$topic_id');" | mysql -pPassword db_name # else # echo "No such theme in db: $topic_id" # echo -e "$topic_id\n$post_id\n$post_date\n$post_text\n\n" >> missed.themes # fi linetodelete=`grep -n "$USER" "$1" | awk -F: '{print $1}' | head -1` echo "line to delete=$linetodelete" sed -i "${linetodelete}d" "$1" count=`expr $count + 1` echo $count done $ find . -maxdepth 1 -type f -name "*php.showtopic*.htm" -exec ./s.sh {} \; topic_id=5500 post_id=106121 date=1199797500 text=Вот то, что за... line to delete=2759 1 post_id=106148 date=1199810040 text=bla-bla line to delete=2998 2 post_id=108758 date=1201491180 text=bla-bla line to delete=4079 3


приветствуется хотя бы идея в виде псевдокода как это все обрабатывать.

не пойму как закрутить цикл так, чтоб внутри цикла:
1) находилось первое совпадение с Юзером (то есть первый пост Юзера в теме)
2) исходя из первого совпадения правдами и неправдами получить значения нужных полей
3) и занести их БД
4) удалить строку с юзером
5)чтоб далее цикл искал далее сообщения юзера в теме и останавливался на первом, но уже новом совпадении
Спасибо сказали:

Аватара пользователя
nerve
Сообщения: 273
ОС: OpenBSD

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение nerve » 22.06.2014 13:24

помогите с регуляркой плз, в обоих случаях надо получить 2594

Shell

# echo "index.php.showtopic=2594.htm" | sed 's/.*=\([0-9]*\).*/\1/' 2594 # echo "index.php.showtopic=2594&st=90.htm" | sed 's/.*=\([0-9]*\).*/\1/' 90



Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 16115
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Solved. Парсить html файлы, находить сообщения по маске и сохранять их в отдельный файл

Сообщение Bizdelnick » 22.06.2014 13:30

sed 's/.*showtopic=\([0-9]\+\).*/\1/'
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали: