Сканирование наличия метрических книг
Написал небольшой скрипт на ПХП для сканирования наличия метрических книг в Национальном Архиве Республики Татарстан. У них на сайте приходится по одному году выуживать, что страшно долго.
Так как некоторые архивы горели, в них могут отсутствовать записи за какие-то периоды. Например, записи по селу Спасское Бугульминского района есть за 1852-1856, 1858, 1861-1864, 1866, 1871-1879, 1884-1889, 1891-1896 и 1898-1917 гг.
Мой сканер задаёт те же вопросы, что и сайт Национального Архива (губернию, уезд и прочее), а на последнем шаге спрашивает диапазон лет для сканирования. В конце работы печатает результат.
Как же мне это всё напоминает программирование двадцать лет назад! «Введите число и нажмите „Ввод“», правда тогда я всё больше на языках ассемблеров писал.
<?
$URL = 'http://www.archive.gov.tatarstan.ru/_go/anonymous/metbooks/';
$COOKIE = '';
// парсим страницу, вынимаем оттуда все теги SELECT
function U_getselects($url, $content = false)
{
if ($content === false) {
global $COOKIE;
$opts = array(
'http' => array(
'method' => 'GET',
'header' => 'Cookie: ' . $COOKIE,
),
);
$content = file_get_contents($url, false, stream_context_create($opts));
foreach ($http_response_header as $header) {
if (preg_match('/^set-cookie:.*?(PHPSESSID=[^; ]+)/i', $header, $m)) {
$COOKIE = $m[1];
break;
}
}
}
$out = array();
$content = iconv('cp1251', 'utf8', $content);
if (preg_match('@<span class="bt4r">([^<>]+)</span>@si', $content, $m)) {
echo 'Ошибка: ', $m[1], "\n";
exit;
}
$mask = '@<span class="bt4b">([^<>]+)(?:<[^>]+>\s*)*?<select\s+.*?name="([^"]+)"[^>]*>(.*?)</select>@si';
if (preg_match_all($mask, $content, $matches, PREG_SET_ORDER)) {
foreach ($matches as $select) {
$options = preg_match_all('/"([^"]+)"/s', $select[3], $m) ? $m[1] : array();
$out[] = array(
'title' => $select[1],
'name' => $select[2],
'options' => $options,
);
}
}
return $out;
}
// Даём пользователю выбрать какой-то пункт из найденного SELECTа
function U_reactselect($select)
{
for (;;) {
echo $select['title'], "\n";
foreach ($select['options'] as $key => $val) {
if (strpos($val, '/') !== false) list(,$val) = explode('/', $val, 2);
printf("% 2d. %s\n", $key + 1, $val);
}
echo "\nПожалуйста, введите номер пункта и нажмите Enter: ";
$value = (int) fgets(STDIN);
if (in_array($value - 1, array_keys($select['options']))) {
echo "\n";
return $select['options'][$value - 1];
}
echo "\n\nТакого пункта нет в списке. Попытайтесь ещё раз, пожалуйста.\n\n";
}
}
// Отправляем запрос
function U_postselect($url, $fields)
{
global $COOKIE;
$fields = array_map(function($item) {
return iconv('utf8', 'cp1251', $item);
}, $fields);
$opts = array(
'http' => array(
'method' => 'POST',
'header' => 'Cookie: ' . $COOKIE . "\r\n".
'Content-type: application/x-www-form-urlencoded',
'content' => http_build_query($fields),
),
);
return file_get_contents($url, false, stream_context_create($opts));
}
// Просим ввести диапазон
function U_getyear($message)
{
echo $message;
$val = (int) fgets(STDIN);
return min(1917, max($val, 1724));
}
$postcontent = false;
for ($step = 1; $step < 3; $step++) {
$choices = array();
foreach (U_getselects($URL, $postcontent) as $select) {
$choices[$select['name']] = U_reactselect($select);
}
$choices['action'] = 'step' . $step;
$choices['to_step' . ($step + 1)] = 'Далее >';
$postcontent = U_postselect($URL, $choices);
}
$choices = array(
'to_step4' => 'Найти',
'action' => 'step3',
);
foreach (U_getselects($URL, $postcontent) as $select) {
$choices[$select['name']] = U_reactselect($select);
}
$from = U_getyear('Введите начальный год: ');
$to = U_getyear('И конечный: ');
if ($from > $to) {
list($from, $to) = array($to, $from);
}
$years = array();
echo "\n";
for ($year = $from; $year <= $to; $year++) {
$choices['year'] = $year;
$postcontent = U_postselect($URL, $choices);
$found =
strpos($postcontent, "\xed\xe5\x20\xed\xe0\xe9\xe4\xe5\xed\xfb") === false &&
strpos($postcontent, "\xed\xe0\xe9\xe4\xe5\xed\xfb") !== false;
if ($found) {
$years[] = $year;
echo '+';
} else {
echo '-';
}
}
if ($years) {
$years[] = INF;
echo "\nАрхив найден за следующие годы: ";
for ($i = 0, $l = sizeof($years); $i<$l-1; $i++) {
if ($i) echo ', ';
echo $years[$i];
for($c = 0, $i++; $i<$l; $i++, $c++) {
if ($years[$i] - $years[$i-1] > 1) {
$i--;
if ($c) {
echo '-', $years[$i];
}
break;
}
}
}
echo "\n";
} else {
echo "\nНичего не найдено.\n";
}
А прикрути к своему сайту, пожалуйста :)
Комментарий для spiridonov@gmail.com:
Увы, он может выполняться куда дольше 30 секунд (у моего хостера есть ограничение на время выполнения скрипта). Может, мне просто найти машину под Виндоус и сделать из него запускаемый файл?
Комментарий для Евгения Степанищева:
Откуда взялся $http_response_header в U_getselects?
Комментарий для miracle.rpz.name:
...век учись..., спасибо.
Забавное.
Комментарий для hshhhhh.name:
Короче, чем while (true) и в некоторых языках быстрее выполняется (так как нет никакого условия, которое надо проверить).
Доброе дело делаете Евгений. Я пятый год пытаюсь составить представление о своих пращурах. Вот настал момент когда остановился. Теперь без метрических записей все остановилось. Начал своих родственников искать, а получилось, что в Маклашеевке (с конца 50-х годов, на дне Куйбышевского водохранилища), ТрехОзерской волости, Спасского уезда, Казанской губернии, где родился мой отец, оказалось семь семей Танкеевых, или 7 генеалогических веток. Соотносительно моего поколения, у прадедов этих ВЕТОК я не знаю отчеств, про года рождения умолчу, а про состав их семей даже и не упоминаю. Несколько месяцев рыскал по просторам интернета и вот сегодня нашел электронный адрес НАЦИОНАЛЬНОГО АРХИВА РЕСПУБЛИКИ ТАТАРСТАН. Разумеется сайт не работает, как буд-то и не существует. И вот еще вышел на Вас.
Живу я в тридевятом государстве тридесятого царства. Приехать в Казань или Ульяновск, где хранятся ревизские Книги, мне как пенсионеру — не по карману. А то, что я собрал по инету не выходя из дому теперь в застое. Если сможете помочь, то ответьте. Мой адрес: pocherk1950@rambler.ru, тогда я вышлю первичные установочные данные.
Еще раз прочел про выуживание раз в год из архива интересующей информации. Поделись опытом. Когда это делапть? Темной ночью или рано утром, в какой день недели, месяц? Или в праздники, когда возможно?
*pocherk1950@rambler.ru*
*
Вроде все, а то написано инкогнито.
Комментарий для Сергей Танкеев:
На сайте НА РТ написано, на самом деле. Одно неудобство — они работают только в рабочие дни в рабочие часы (т. е. вечером после работы я не могу там посидеть), поэтому я нанимаю людей, которые делают это за меня.
Комментарий для Сергей Танкеев:
Сайт Национального Архива сейчас и правда не работает ( http://www.archive.gov.tatarstan.ru ), но, думаю, это временное явление. Я не смогу вам помочь в Архиве, но они работают по электронном почте: nart.archive@tatar.ru, выполнение запроса стоит 200 рублей за документ.
Спасибо, попробую. А тебе здоровья, хороших идей и их воплощения.