Как эффективно извлечь информацию из data.gov.in
4 шага для извлечения любого объема данных с использованием node.js
Я решил написать этот блог-пост, потому что считаю, что это может помочь многим людям получить легкий доступ к данным, предоставляемым правительством. Кроме того, процесс извлечения информации с сайта является трудоемким, поскольку данные разделены на тысячи точек данных, которые необходимо загружать индивидуально.
Извлечение данных из data.gov.in не так просто, и это довольно длительный процесс, который включает несколько шагов.
В этой статье мы рассмотрим четыре основных шага по загрузке данных с data.gov.in:
Давайте перейдем к первому шагу!
1. Найдите шаблон, относящийся к данным, которые вы хотите скачать
На следующем gif-изображении я покажу, как найти шаблон, относящийся к данным о производительности ключевых показателей HMIS по районам:
2. Определите, какую информацию и данные вам нужно
В этом руководстве мы собираемся получить информацию, такую как название района, год и месяц, а также JSON-файл для каждой точки данных.
После изучения заголовка и элементов данных с помощью инструмента "Инспектировать элемент", мы определяем HTML-теги, которые веб-сайт использует для этой конкретной информации, которую мы будем использовать позже.
3. Использование правильного набора библиотек Node.js
Мы собираемся использовать мощные библиотеки Node.js, которые также используются для тестирования и контроля качества во многих компаниях. Для наших целей они идеально подходят.
Начните с создания проекта Node и установки puppeteer и его зависимостей с помощью npm.
Мы собираемся писать асинхронный код на ES6-javascript.
const puppeteer = require('puppeteer');
const fs = require('fs');
var download = require('download-file');
После импорта зависимостей мы пишем функцию, которая помогает сохранить URL-адреса для файлов JSON. Не забудьте использовать правильные соглашения по именованию файлов.
const save = async (value,state,district) => {
var jsonContent = JSON.stringify(value); var dir = ".\\WholeUrls\\"+state; if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
} saveLoc=".\\WholeUrls\\"+state+"\\"+district+".json"
fs.writeFile(saveLoc, jsonContent, 'utf8', function (err) {
if (err) {
console.log("Произошла ошибка при записи объекта JSON в файл.");
return console.log(err);
}
console.log("Файл JSON был сохранен.");});
}
Затем мы пишем функцию для парсинга страницы:
const scrapePage =async (page) => page.evaluate(() => {let url = []; //Пустой массив для URL-адресов
let title = [];
let elements = document.querySelectorAll('.csv');
for (var element of elements){
url.push(element.href);
}elements = document.querySelectorAll('.title-content');
for (var element of elements){
title.push(element.innerText);
}let data = {title,url};return data;
})
Вышеуказанный код использует библиотеку puppeteer для навигации по 1 странице. Как мы видели на GIF-изображении, каждая страница содержит 6 точек данных. Таким образом, приведенный выше код запускает и извлекает информацию и данные о 6 точках данных.
Но согласно нашим экспериментам, если вам нужно извлечь данные для примерно 22 000 существующих точек данных, нам нужно добавить возможность навигации в наш код. Так, чтобы он самостоятельно перемещался и выполнялся, пока успешно не загрузит все данные.
let scrape = async (district="BAKSA",state="ASSAM") => {
console.log("Начался парсинг для ", district)
let iterator=0;
d=district.toLowerCase()
d1=""for(const i in d){
if(i!=' ') d1+=d[i]; else break;
}const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
//для всех URL-адресов
urls=[]
uRl='[https://data.gov.in/search/site?filter%5Bnew_title'](https://data.gov.in/search/site?filter%5Bnew_title%5D=farmers+queries+kisan+call+centre+%27+d1+%27+district+month%27)
await page.goto(uRl);
i1=1;
while (1){
for (let i = 0; i < 10; ++i) {
let Result;
Result = `#ogpl-cust-result-html-wrap > div:nth-child(${i + 1}) > h3 > a`;
try{
await page.waitFor(Result, {visible: true});
}
catch(err){
console.log("Пришли сюда")
i1=0;
break;
}
err1=false;
page.click(Result);
try{
await page.waitForNavigation({waituntil:'networkidle2'});
}
catch(err){
console.log("поймана ошибка:",err);
err1=true;
}
if(!err1){
//const url = page.evaluate(()=> {uRL= document.querySelector('.csv');return uRL.href;})
try{
url= await scrapePage(page);
urls.push(url);
}
catch(err){
console.log("ошибка страницы:",err);
}
my=(url["title"][0]).split(" ");
year=my[my.length-1];
month=my[my.length-2];options = {
directory: "./WholeData/"+state+"/"+district+"/",
filename: year+" "+month+".csv",
timeout: 2000000
};
})
}
await page.waitFor(1000);
await page.goBack();
await page.waitFor(2000);
}
if(i1==0)
break;let Result = `#ogpl-cust-result-pager-wrap > div > ul > li:nth-child(2) > a`;
try{
await page.waitFor(Result, {visible: true});
}
catch(err){
Result = `#ogpl-cust-result-pager-wrap > div > ul > li > a`;
}
page.click(Result);
try{
await page.waitForNavigation({waituntil:'networkidle2'});
}
catch(err){
console.log("Ошибка:",err);
}
}browser.close();if(JSON.stringify(urls)!="[]")
save(urls,state,district)return new Promise((resolve)=> resolve('resolved'));};module.exports = {scrape};
4. Используйте download.js для сохранения загруженных данных в организованном формате
my=(url["title"][0]).split(" ");
year=my[my.length-1];
month=my[my.length-2];options = {
directory: "./WholeData/"+state+"/"+district+"/",
filename: year+" "+month+".csv",
timeout: 2000000
};if(url)
download(url["url"][0], options, function(err){
if (err) {console.log(url["url"][0],err);return err;}
else {console.log(url["url"][0], "location=",state,district,month,year,"meow");return true};
Функция сохраняет данные в папке с названием "WholeData", с определенным именем файла и соответствующими подпапками.
5. Заключение
В этом руководстве вы узнали, как извлекать любую информацию, которую вы хотите, с сайтов, таких как data.gov.in, которые не могут быть спарсены обычными способами, даже с сайтов, требующих заполнения форм и навигации.