obshtestvo / sledi-parlamenta

Надежден инструмент за справки и анализ на парламентарната активност
http://parliament.obshtestvo.bg/
The Unlicense
13 stars 3 forks source link

Извличане на спечелени европейски проекти/конкурси #41

Open antitoxic opened 10 years ago

antitoxic commented 10 years ago

Проверка в ИСУН

gif_screencast_10

http://umispublic.minfin.bg/ Система за търсене на спечелени европейски поръчки и конкурси. Търси се по име на фирма, като на сайта се използват термините "Бенефициент", "Партньор", "Изпълнител".

Проблем е, че тук не са регистрирани проектите по Програма Развитие на селските райони.

Характерно за тази система е, че фирмите са вписани фриволно - големи, малки букви, кавички, без кавички, с оказване на вида фирма (еоод, оод, ет..), без оказване и т.н. Има случаи на разминаване между регистрираното име в ТР и в ИСУН - това е явление, основно при фирми, чиито имена не са български. При автоматизиране трябва да генерираме множество варианти на име и да генерираме дори възможни грешни изписвания. Друго да се вземе предвид: тирета и фонетично изписване на английско звучене.

Системата е доста бавна. Тоест технически погледнато кода трябва да е написан така че да се справя с неуспешни опити да се заредят някой страници и да се паузира извличането за даден период и пак да се пробва.

simov commented 10 years ago

:wave: вчера гледах презентацията на VarnaConf и се подсетих за вашият проект. Написах кратък скрипт, който взима съдържанието от Списък на проектите, резултат тук

[
    {
        "beneficiary": "\"Mеги 96\" ООД",
        "residence": "Област: София град Oбщина: Столична 1000 София гр. София, район Люлин, ж.к.\"Люлин\" бл.320, вх.Б, ет.4, ап.34",
        "place": "България; ЮГОЗАПАДНА И ЮЖНА ЦЕНТРАЛНА БЪЛГАРИЯ; Югозападен; Перник; Брезник",
        "agreement": "<a href=\"srchProjectInfo.aspx?id=3094\">\"Повишаване на конкурентноспособността на МЕГИ 96 ООД чрез покриване изискванията на стандарт ISO 9001:2000\"\r\n</a>",
        "cost": "101 185",
        "bfp": "49 581",
        "payed_from_beneficient": "51 604",
        "payed": "49 581",
        "duration": "12,00",
        "status": "Приключен",
        "contractors": "<br><a href=\"iBeneficientProjects.aspx?benef=4776\">\"Интегрити Консултинг\" ООД</a><br><a href=\"iBeneficientProjects.aspx?benef=7632\">\"Сертификейшън Интернешънъл България\"</a><br><a href=\"iBeneficientProjects.aspx?benef=7665\">БИОУИН ПРОЕКТ</a><br><a href=\"iBeneficientProjects.aspx?benef=7890\">РИП 2002</a><br><a href=\"iBeneficientProjects.aspx?benef=7891\">ЗАР96</a>"
    },
    ...
]

Страницата за разширено търсене не се зарежда, а експорта, който се намира в списъка с проектите е много бавен, с този скрипт дръпнах информацията за ~3мин (някои от колоните трябва да се обработят допълнително)

var fs = require('fs');
var request = require('request'),
    async = require('async'),
    cheerio = require('cheerio');

var total = 11495, pages = Math.ceil(total/10), page = 1;

var columns = ['beneficiary', 'residence', 'place', 'agreement', 'cost', 'bfp',
    'payed_from_beneficient', 'payed', 'duration', 'status', 'contractors'];

var json = [], errors = [];

function get (page, done) {
    request.post(
        'http://umispublic.government.bg/prProcedureProjectsInfo.aspx?op=-1&proc=-2&clear=1', {
            form:{
                tvMainMenu_ExpandState:'ennnnnnnennnnnnnennnenenenen',
                tvMainMenu_SelectedNode:'tvMainMenut21',
                __EVENTTARGET:'ctl00$ContentPlaceHolder1$CtlListPager1$hl_'+page,
                __VIEWSTATE:'copy/paste some view state hash here!'
            }
        }, function (err, res, body) {
            if (err) return done(err);
            done(null, body);
        }
    );
}

function parse (html) {
    var $ = cheerio.load(html);

    $('.InfoTableProposal tr').each(function (index) {
        if (!index) return;
        var row = {};
        $(this).find('td').each(function (index) {
            row[columns[index]] = $(this).html().trim();
        });
        json.push(row);
    });
}

async.eachLimit(Array(pages), 5, function (dummy, done) {
    var _page = page++;
    get(_page, function (err, html) {
        if (err) {
            console.log('Page', _page, err);
            errors.push({page:_page, message:err.message});
        }
        parse(html);
        console.log('Page', _page, 'processed');

        done();
    });
}, function () {
    fs.writeFileSync('result.json', JSON.stringify(json, null, 4), 'utf8');
    fs.writeFileSync('errors.json', JSON.stringify(errors, null, 4), 'utf8');
    console.log('DONE!');
    process.exit();
});

async.until(
    function test () {
        return page >= pages;
    },
    function job (done) {
        setTimeout(function () {
            fs.writeFileSync('result.json', JSON.stringify(json, null, 4), 'utf8');
            fs.writeFileSync('errors.json', JSON.stringify(errors, null, 4), 'utf8');           
            console.log('File saved');
            done();
        }, 15000);
    },
    function done () {
        console.log('DONE!');
    }
);
antitoxic commented 10 years ago

Евала @simov ! :smiley:

Имаш ли кода в нещо като repo, за да ти merge-нем усилията и да се знае, че си го писал ти? Алтернативно мога да копирам кода и да го добавя в прокта?

simov commented 10 years ago

@antitoxic мога да направя PR. Проблемът е че все още не съм се запознал напълно с проекта, и не съм сигурен в коя директория трябва да отиде, как да я кръстя и тн.

Иначе този скрипт дърпа само информацията, може да се доработи малко, главно в полето agreement и contractors се намират разни id-та, но и за базата, която използвате не бях сигурен :smiley:

antitoxic commented 10 years ago

Тук https://github.com/obshtestvo/sledi-parlamenta/tree/master/data_mining си правиш една директория например eu-tenders

И заедно със скрипта удряш едно README за употреба.

Туй то :smiley: . Не се тревожи за базата. Идеята е тия скриптове да Output-ват 1 обект на ред. Тоест в тоя случай инфото за 1 поръчка на ред.

Мислил ли си дали искаш да доработиш скрипта?

Примерно от:

    request.post(
        'http://umispublic.government.bg/prProcedureProjectsInfo.aspx?op=-1&proc=-2&clear=1', {
            form:{
                tvMainMenu_ExpandState:'ennnnnnnennnnnnnennnenenenen',
                tvMainMenu_SelectedNode:'tvMainMenut21',
                __EVENTTARGET:'ctl00$ContentPlaceHolder1$CtlListPager1$hl_'+page,
                __VIEWSTATE:'copy/paste some view state hash here!'n',
...

ми изглежда че някой неща са hardcode-нати, но понеже не съм навилиза навътре в сайта не знам защо и има ли начин да не са?

simov commented 10 years ago

ОК, ще пусна един PR (има неща за дооправяне).

Въпросът ми за базата беше свързан с това, че agreement и contractors съдържат извадка от реалният обект, тоест name и id, и вече зависи дали използвате sql или nosql база. Така или иначе ще дръпна и останалата информация от сайта, останалото може да се изясни и в последствие.

Колкото до хардкоднатите параметри, това е query string-a, с който сървъра работи, тоест тези параметри са статични, единствената промяна е page