LINUX.ORG.RU

[find][sed][regexp][php]Прошу помочь обработать скриптом очень большое количество текстовых файлов.

 , , ,


0

0

Здравствуйте уважаемые обитатели этого форума!

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

В связи с нерегулярным доступом в сеть, мне захотелось иметь у себя на ноутбуке локальную копию сайта-коллекции текстов песен с аккордами для гитары. Обычно за аккордами для нужной песни я хожу на amdm.ru, поэтому я и попытался тупо скачать весь этот сайт, но администрация этого ресурса наложила ограничения на пользователей, скачать сайт не удается. Ну я и открыл для себя pesenki.ru

Скачиваю сайт целиком с помощью такого вот заклинания:

nohup wget -c --mirror --convert-links --no-verbose --no-parent \
--page-requisites --user-agent="Mozilla/5.0 (compatible; \
 Konqueror/4.3; Linux 2.6.30-2-amd64; X11; x86_64; ru) KHTML/4.3.2 (like Gecko)"  pesenki.ru &


Качаю уже несколько дней, ибо во-1х канал не особо широк, и во-2х, через несколько часов работы процесс wget потихоньку заполняет собой всю оперативную память и комп люто бешено висит, почти не реагируя ни на что. В общем, пока скачалось примерно 280 000 страниц, общим размеров примерно 5 Гб.

Это присказка. Смешно будет дальше.

По интернетам я ползаю посредством iceweasel, а локальные html-файлы у меня по дефолту открываются konqueror-ом. На iceweasel конечно же установлен adblock, а на konqueror конечно нет, поэтому, когда я открыл им для проверки одну из скачанных страничек - мягко говоря, удивился - аккуратный и прилежный сайт-справочник превратился в сплошное ПЫЩЬ ПЫЩЬ ОЛОЛОЛО, реклама была повсюду.

Я взглянул на исходный код и был поражён. Одна из страничек с сайта pesenki.ru, для примера). Я проникся искренним сочуствием к тем пользователям, которые не знают о таком счастье, как adblock... Но не суть.

Встала задача выпилить к чертовой матери все ненужное из исходного кода. Относительно элегантно проблема должна была решиться бы, если бы удалось удалить блоки текста такого вида: <script.*?</script> и по аналогии с другими тэгами.

Я долго экспериментировал со связкой команд find и sed, и периодически что-то у меня получалось. В итоге самое умное до чего я додумался это что-то такое примерно:

find /home/leonder/downloads/pesenki.ru/ -iname "*html" -print0 |  \ 
xargs -0 -P 2 sed -e '/<script/,/<\/script>/d' \
 -e '/<noscript/,/<\/noscript>/d' -e '/<iframe/,/<\/iframe>/d' \
 -e '/<!--/,/-->/d' 


но тут я столкнулся с проблемой...

Выражаясь человеческим языком, от sed мне нужно следующее: найти и вырезать куски текста, соответствующие шаблону - ПЕРВОЕ вхождение сроки «<script», потом сколько угодно любого текста вплоть до ПЕРВОГО же вхождения строки «</script>». Но мне так и не удалось составить нужное рег. выражение ((( А то, что я употребил - находит текст между ПЕРВЫМ вхождением ПЕРВОГО выражения и ПОСЛЕДНИМ вхождением второго выражения.

Нужного эффекта мне когда-то ранее (давно) удавалось добиться на PHP, когда я написал скрипт - своеобразное зеркало башорга. В общем я посидел ночь и сваял вот такое рекурсивное чудо, которое работает иначе - не вырезает ненужный код, а наоборот - компонует новый файл из нужных кусков:

<?php

$count=0;
function cleancode($dirname)
{
	global $count;
	$dir = opendir($dirname);
	while (($file = readdir($dir)) !== false)
	{
		if($file !== "." && $file !== "..")
		{
			//Если очередной $file - каталог, то нырнуть в него, рекурсивно применя функцию
			$sub_dir = $dirname.'/'.$file;
			if(is_dir($sub_dir))
			{
				cleancode($sub_dir);
			}
			$file_arr=explode(".", $file);
			$ext = strtolower(end($file_arr));
			if( $ext=="shtml" || $ext=="html" || $ext=="htm" )
			{
				$file_source_all[][$dirname]=$file;
				#echo $dirname.'/'.$file.'<br/>';
				$file_content = file_get_contents ($dirname.'/'.$file);

				$pattern="'<script[^>]*?>.*?</script>'si";
				$pattern1="'<noscript[^>]*?>.*?</noscript>'si";
				$pattern2="'<iframe[^>]*?>.*?</iframe>'si";
				$pattern3="'<br><noindex>.*?</noindex>'si";

				$replace="";
				$file_content=preg_replace($pattern, $replace, $file_content);
				$file_content=preg_replace($pattern1, $replace, $file_content);
				$file_content=preg_replace($pattern2, $replace, $file_content);
				$file_content=preg_replace($pattern3, $replace, $file_content);


				$new_file_content = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
	<title>Локальная копия сайта pesenki.ru</title>
	<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
<body bgcolor="#e5e5e5">
				';

				preg_match('#<strong style="font-size:110%;">(.*?)</strong>#si',$file_content,$res);
				$new_file_content.=$oglavlenie = $res[0].'<br><br>';

				preg_match('#<div class=zag>(.*?)</div>#si',$file_content,$res);
				$new_file_content.=$div_zag = $res[0].'<br>';

				preg_match('#<div class=wzag>(.*?)</div>#si',$file_content,$res);
				$new_file_content.=$div_zag2 = $res[0].'<br>';

				preg_match('#<font><b>(.*?)</b></font>#si',$file_content,$res);
				$new_file_content.=$list = $res[0].'<br>';

				preg_match_all('#<td class=m1><b><a href="(.*?)><b class=(.*?)</a>#si',$file_content,$res);
				foreach ($res[0] as $link) $new_file_content.= $list2 = str_replace(' class=ctxt','',$link).'<br>';

				preg_match('#<pre>(.*?)</pre>#si',$file_content,$res);
				$new_file_content.= $text_with_chords = $res[0];

				$new_file_content.='</body></html>';

				if(file_put_contents('/tmp/cleaning/'.$file, $new_file_content))
				{
					$count++;
					$percent=round($count/670,2);
					echo '<b>'.$percent.'%</b>, файл №'.$count.' из 70000, '.$dirname.'/'.$file.': <b>Завершено!</b><br/>' ;
				}
			}
		}
	}
	closedir($dir);
}

cleancode('/home/leonder/downloads/pesenki.ru/authors/');

?>


В общем-то это работает, но я чую, что делаю очень неправильные действия. Например, наверное, надо этот php скрипт модифицировать так, чтобы он принимал на вход имя файла и обрабатывал только его (не умею)... или еще как-то. Ибо опция max_execution_time должна вроде как твикаться до получаса у php.ini...

В общем, дорогие товарищи, помогите советами пожалуйста!
Заранее большое спасибо за внимание тем, кто решится его уделить!

perl -i.bak -ne 'if (/<script/i)   { $f=1     };  \
                 if ($f==0)        { print $_ };  \
                 if (/<\/script/i) { $f=0     }'  besimsa-chords.shtml 
sdio ★★★★★
()

>По интернетам я ползаю посредством iceweasel, а локальные html-файлы у меня по дефолту открываются konqueror-ом.

что мешает настроить, чтобы локальные файлы открывались в мозилле? :)

nu11 ★★★★★
()

если тебе не нужна визуальная мишура, а нужен только текст со страниц, то делается все гораздо проще:

find <path> -iname "*html" -print0 | xargs -0 \
php -r "$html=file_get_contents($argv[1]); $phpdom = new DOMDocument(); @$phpdom->loadHTML($html); file_put_contents($argv[1],$phpdom->textContent);"

nu11 ★★★★★
()

поправка

find <path> -iname "*html" -print0 | xargs -0 \
php -r '$html=file_get_contents("$argv[1]"); $phpdom = new DOMDocument(); @$phpdom->loadHTML($html); file_put_contents("$argv[1]",$phpdom->textContent);' --

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

проще все таки открывать страницы в мозилле :) Или настроить таки adblock в конке.

nu11 ★★★★★
()
drull@ubuntu:~$ cat fillle
aaaaaaaaaaaaaaaaaaaa
<script>11111111</script>
bbbbbbbbbbbbbbbb
<script>222222222222222</script>
ccccccccccccccccccccccc
drull@ubuntu:~$ sed "s/<script.*<\/script>//" fillle
aaaaaaaaaaaaaaaaaaaa

bbbbbbbbbbbbbbbb

ccccccccccccccccccccccc

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

да, но как показала практика, этого вполне достаточно чтоб срезать хоть половину рекламы. только что проверил на страничке которую ТС дал для примера: убирается контекстная реклама бегуна(справа), баннер от imhonet (сверху) и большой баннер слева.

drull ★☆☆☆
()

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

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

>а насчет пхп скрипта - принимай имя через ГЕТ-запрос.

какой GET в консольном скрипте, о чем вы? :)

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

ну поднять вебсервер слушающий на локалхосте?

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