Мини заметки — выпуск 5
23 января 2012
Основные темы пятого выпуска: FreeBSD, Haskell, парное программирование, алгоритм шифрования lameCrypt на Perl и отрывки кода на PHP, имеющие отношение к поисковой оптимизации. Предыдущие выпуски: первый, второй, третий и четвертый.
1. Один интересный прием на Haskell
Этот отрывок кода я подглядел в архиве почтовой рассылки haskell-cafe:
ScopedTypeVariables, OverlappingInstances #-}
import System.Random
class (Bounded a, Enum a) => BoundedEnum a
instance (Bounded a, Enum a) => BoundedEnum a
instance BoundedEnum a => Random a where
random gen = randomR (minBound :: a, maxBound :: a) gen
randomR (f, t) gen =
(toEnum r :: a, nextGen)
where
(rnd, nextGen) = next gen
r = fromEnum f + (rnd `mod` length [f..t])
Он позволяет говорить…
…для любого типа Anything, являющегося экземпляром классов Enum и Bounded. Это позволяет не писать множество функций genRandomTypeN для каждого типа TypeN. В некоторых программах такой прием может быть очень полезен.
2. Удаленное парное программирование в screen
Есть несколько способов организовать удаленное парное программирование. Можно использовать для этого VNC или вашу IDE (такая возможность точно есть в Visual Studio, а также существует несколько плагинов для Eclipse). Но если вы и ваши коллеги предпочитают использовать VIM, то для удаленного парного программирования вы можете использовать утилиту screen.
Допустим, программисты с никами afiskon и eax решили программировать в паре с использованием screen. Для этого afiskon заходит на unix-сервер, где также имеет учетную запись eax, и говорит:
:multiuser on
:acladd eax
Затем eax заходит на тот же сервер и выполняет команду:
Вот и все! См также man screen, особенно его часть про управление доступом (команда aclchg).
3. Оптимизация сайта под запросы с опечатками
Эту идею я подглядел на Blogerator.ru (см конец статьи). Идея состоит в том, чтобы находить в статье словосочетания на латинице и дописывать в конце эти словосочетания, набранные в русской раскладке. Например, если в статье встречаются слова «perl», «freebsd» и «haskell», то в конце статьи должно быть написано «зукд», «акууиыв» и «рфылудд». Это дело несложно автоматизировать:
$content = preg_replace('/<[^>]+?>/', '', get_the_content());
preg_match_all('/\s+([a-z][a-z_\-\ ]{3,}[a-z])\s+/i',
$content, $match);
// приводим их к нижнему регистру и удаляем повторы
$keywords = array_map("strtolower", $match[1]);
$keywords = array_slice(array_unique($keywords), 0, 10);
// получаем опечатки
$replaceFrom = "abcdefghijklmnopqrstuvwxyz";
$replaceTo = mb_convert_encoding("фисвуапршолдьтщзйкыегмцчня",
"CP-1251", "UTF-8");
$funcCode =
'return mb_convert_encoding('.
'strtr($x, "'.$replaceFrom.'", "'.$replaceTo.'"), '.
'"UTF-8", "CP-1251");';
$rusKeywords = array_map(create_function('$x',$funcCode), $keywords);
// объединяем
$keywords = implode(", ", array_merge($keywords, $rusKeywords));
Я проверял, трафик с поисковых систем действительно увеличивается. Однако следует отметить, что Яндекс обещал жестоко наказывать за переоптимизацию сайтов, так что подумайте перед тем, как пользоваться это «темой».
4. BlogSpot + ZoneEdit
Если вы хотите создать сайт, но деньги есть только на доменное имя (от 100 рублей в год), воспользуйтесь следующей последовательностью шагов:
- Создаем блог на blogspot.com;
- Регистрируемся на zoneedit.com;
- Регистрируем доменное имя;
- Присваиваем доменному имени DNS’ы от ZoneEdit (например, ns5.zoneedit.com и ns7.zoneedit.com);
- Через ZoneEdit ставим в соответствие домену IP-адреса блогспота (на данный момент это 216.239.38.21, 216.239.32.21, 216.239.34.21 и 216.239.36.21);
- Проверяем настройки с помощью whois и dig (помним, что на обновление зоны нужны сутки);
- Если все ОК, прописываем в свойствах блога доменное имя;
- Получили бесплатный хостинг и бесплатные DNS сервера. Оплате подлежит только продление домена раз в год;
О том, как заработать на таком сайте, вы можете узнать из заметки Схема заработка в GoGetLinks, которая работает. Из недостатков приема — (1) зависимость от BlogSpot и ZoneEdit, (2) о добавлении сайта в SAPE придется забыть.
5. OpenDNS и GoogleDNS
OpenDNS:
nameserver 208.67.220.220
GoogleDNS:
nameserver 8.8.4.4
Запомнить наизусть!
6. Определение объема свободной памяти во FreeBSD
Во FreeBSD для определения суммарного объема свободной оперативной памяти с помощью, скажем, утилиты top требуется произвести дополнительные вычисления в уме. Я лично все время забываю, что с чем нужно складывать, поэтому предпочитаю использовать утилиту freecolor (легко ставится из пакеджей или портов).
На приведенном скриншоте freecolor говорит, что 34% оперативной памяти (703 Мб) свободно. Все просто и понятно.
7. Проверка IP на наличие в спам-списках
Перепост отсюда:
www.senderbase.org/senderbase_queries/detailip?search_string=1.1.1.1
support.clean-mx.de/clean-mx/publog?ip=1.1.1.1
www.spamcop.net/w3m?action=checkblock&ip=1.1.1.1
Еще больше таких сервисов можно найти здесь.
8. Как не нужно шифровать данные
Некоторые задачи требуют быстрого решения. Если у вас нет времени на установку CPAN-модуля Crypt::Rijndael (код требуется развернуть на сотне серверов, нужен таск на админов, …), можете воспользоваться алгоритмом вроде этого:
use strict;
use Digest::MD5 qw/md5_hex/;
#use String::CRC32 qw/crc32/;
#sub md5_hex { sprintf("%08x", crc32(@_)) }
sub lameCrypt {
my ($str, $key, $decrypt) = @_;
return '' unless length($str);
unless($decrypt) {
my $iv = '';
while(length($iv) < 16) {
my $t; $t .= rand() for(0..7);
$iv .= md5_hex($iv.time().$$.$t);
}
$str = substr($iv, 0, 16).unpack("h*", $str);
}
my $l_len = int(length($str)/2);
my $r_len = length($str) - $l_len;
my $splitRe = qr/^(.{$l_len})(.{$r_len})$/o;
my ($rounds, $left, $right) = (32, undef, undef);
for my $i(1..$rounds) {
($left, $right) = $str =~ $splitRe;
my $f = '';
while(length($f) < $r_len) {
$f .= md5_hex(
$f.$left.($decrypt ? $rounds - $i + 1 : $i).$key
);
}
my $j = 0;
$right = join '', map {
sprintf("%x", hex($_)^hex(substr($f, $j++, 1)))
} split(//, $right);
$str = $right.$left;
}
$str = $left.$right;
return $str unless($decrypt);
return pack("h*", substr($str, 16, length($str)-16));
}
my $str = "secret message";
my $key = "aaa123";
my $enc = lameCrypt($str, $key, 0);
my $dec = lameCrypt($enc, $key, 1);
print "str = $str\nenc = $enc\ndec = $dec\n";
Алгоритм представляет собой сеть Фейстеля, причем размер блока равен длине (де)шефруемой строки. Если в строке нечетное количество байт, то при разбиении блока левая половина делается на один байт меньше правой. Функция F основана на алгоритме MD5.
Приведенный способ будет понадежнее какого-нибудь шифрования с помощью XOR, но он все равно ненадежен. Используйте приведенный код только в экстренном случае и только в качестве временного решения. Перед использованием обязательно внесите в алгоритм пару изменений (используемая хэш-функция, число итераций и тп).
9. FreeBSD — установка модулей Python из PyPI
Для установки модулей Python под FreeBSD оказалось очень удобно использовать утилиту pip.
pip search wordpress # поиск модулей
pip install pil # установка модуля
pip uninstall pil # удаление модуля
pip freeze # список установленных модулей
См также http://pypi.python.org/pypi.
10. Статистика поисковых запросов своими руками
В каком-нибудь footer.php дописываем:
$ref = $_SERVER['HTTP_REFERER'];
if(preg_match('/^http:\/\/(www\.)?(yandex|google)/', $ref)) {
$fid = fopen("/path/to/ref.txt", "a");
fwrite($fid, date("Y-m-d")."\t".$_SERVER['REQUEST_URI']."\t$ref\n");
fclose($fid);
}
?>
Ждем пару недель, после чего скармливаем файл ref.txt следующему скрипту:
# ref.txt parser v 0.1
# (c) Alexandr A Alexeev 2012 | http://eax.me/
use strict;
use warnings;
use utf8;
use URI::Escape;
my $gre= qr"www\.google\.[^/]+/.*?[\#\?\&]{1}(?:as_)?q=([^\&]*)"i;
my $yre= qr"yandex\.[^/]+/.*?[\?\&]{1}(?:text|query)=([^\&]*)"i;
my $ire= qr"www\.google\.[^/]+/(notebook|reader|imgres|webhp)"i;
my %stat; # {url \t query} = cnt
my $fails = 0;
while(my $line = <>) {
chomp($line);
my($date, $url, $ref) = split /\t/, $line;
my $query;
if($ref =~ $gre) {
$query = $1;
} elsif($ref =~ $yre) {
$query = $1;
} else {
next if($ref =~ m"^http://[^/]+/?$"i);
next if($ref =~ m"www\.google\.[^/]+/search$"i);
next if($ref =~ m"doubleclick\.net/pagead/"i);
next if($ref =~ $ire);
warn "Failed to parse: $ref\n";
$fails++;
}
next unless($query);
$query = uri_unescape($query);
$query =~ s/\+/ /g;
$query =~ s/\s+/ /g;
$query = lc($query);
$stat{"$url\t$query"}++;
}
if($fails) {
warn "Total fails: $fails\n-----------\n";
}
for my $url_query(sort { $stat{$b} <=> $stat{$a} } keys %stat){
my($url, $query) = split /\t/, $url_query;
my $cnt = $stat{$url_query};
printf "%09d\t%s\t%s\n", $cnt, $url, $query;
}
Затем можно прогнать полученный список запросов через wordstat.yandex.ru и закупить внешних ссылок или провести внутреннюю оптимизацию сайта (перелинковка, заголовки и тп).
Собственно, это все. Как обычно, я буду несказанно рад вашим комментариям и вопросам.
Дополнение: Мини заметки — выпуск 6
Метки: Всячина.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.