UNPKG

@democracy-deutschland/bt-named-polls

Version:

scraper for the german "Bundestag" (Namentliche Abstimmungen)

171 lines (145 loc) 5.45 kB
'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _Browser = require('./Browser'); var _Browser2 = _interopRequireDefault(_Browser); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* eslint-disable max-len */ /* eslint-disable no-throw-literal */ process.setMaxListeners(Infinity); class Scraper { constructor() { var _this = this; this.options = { startId: 1, onData: false, onFinish: false }; this.urls = { get: ({ id }) => `https://www.bundestag.de/parlament/plenum/abstimmung/abstimmung?id=${id}`, getPolls: ({ offset }) => `https://www.bundestag.de/ajax/filterlist/de/parlament/plenum/abstimmung/484422-484422/?noFilterSet=true&offset=${offset}`, start: null }; this.browser = null; this.scrapedWeeks = []; this.dataPromises = []; this.lastTitle = ''; this.pollIds = []; this.getAvailablePolls = _asyncToGenerator(function* () { const { browser: { browser } } = _this; let offset = 0; let results = true; while (results) { const { body } = yield browser.request({ uri: _this.urls.getPolls({ offset }) }); const polls = body.match(/<a href="\/parlament\/plenum\/abstimmung\/abstimmung\?id=(\d*)"/g); if (polls) { _this.pollIds = [..._this.pollIds, ...polls.map(function (poll) { return parseInt(poll.match(/(\d+)/)[1], 10); })]; offset += polls.length; } else { results = false; } } _this.pollIds = [...new Set(_this.pollIds)].filter(function (pollId) { return pollId >= parseInt(_this.options.startId, 10); }); }); this.getClosestPollId = id => { if (Math.max(this.pollIds < id)) { return false; } const closest = this.pollIds.reduce((prev, pollId) => { const diff = pollId - id; if (diff >= 0 && (prev === false || pollId <= prev)) { return pollId; } return prev; }, false); const index = this.pollIds.indexOf(closest); if (index > -1) { this.pollIds.splice(index, 1); } return closest; }; this.getPolls = (() => { var _ref2 = _asyncToGenerator(function* ({ id }) { let curId = _this.getClosestPollId(id); if (!curId) { throw new Error('Poll id is to high!'); } const { browser: { browser } } = _this; let { body } = yield browser.request({ uri: _this.urls.get({ id: curId }) }); let { title, date, documents } = browser.getHead(body); let errorCount = 0; while (curId && errorCount < 5) { _this.lastTitle = title; ({ body } = yield browser.request({ uri: _this.urls.get({ id: curId }) })); try { ({ title, date, documents } = browser.getHead(body)); const voteResults = browser.getPartyVotes(body); const resultData = { id: curId, title, date, documents, voteResults }; if (_this.options.onData) { _this.dataPromises = [..._this.dataPromises, _this.options.onData(resultData)]; } errorCount = 0; } catch (error) { errorCount += 1; } curId = _this.getClosestPollId(curId); } }); return function (_x) { return _ref2.apply(this, arguments); }; })(); this.createNewBrowser = (() => { var _ref3 = _asyncToGenerator(function* ({ browserObject } = {}) { if (browserObject) { delete browserObject.browser; // eslint-disable-line } const browser = new _Browser2.default(); yield browser.initialize(_this.urls.start); return { browser, used: false, scraped: 0, errors: 0 }; }); return function () { return _ref3.apply(this, arguments); }; })(); } scrape(options) { var _this2 = this; return _asyncToGenerator(function* () { _this2.options = _extends({}, _this2.options, options); _this2.urls.start = _this2.urls.get({ id: _this2.options.startId }); _this2.browser = yield _this2.createNewBrowser(); yield _this2.getAvailablePolls(); yield _this2.getPolls({ id: parseInt(_this2.options.startId, 10) }); if (_this2.options.onFinish) { yield Promise.all(_this2.dataPromises); yield _this2.options.onFinish({ length: _this2.dataPromises.length }); } })(); } } module.exports = Scraper;