Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
antitoxic opened this issue Dec 10, 2013 · 5 comments
Labels

Comments

@antitoxic
Copy link
Member

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

gif_screencast_10

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

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

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

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

@tsikov tsikov added the scraper label Apr 11, 2014
@simov
Copy link

simov commented Jul 13, 2014

👋 вчера гледах презентацията на 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
Copy link
Member Author

Евала @simov ! 😃

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

@simov
Copy link

simov commented Jul 28, 2014

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

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

@antitoxic
Copy link
Member Author

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

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

Туй то 😃 . Не се тревожи за базата. Идеята е тия скриптове да 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
Copy link

simov commented Jul 28, 2014

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

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants