정당한 이유 없이 영화 등급 분포 그래프 작성
28043 단어 javascriptmovies
등급 시스템 웹 사이트https://www.filmratings.com/에서 나 자신을 발견했고 특정 연도 및 등급에 대한 영화를 찾을 수 있는 검색 엔진이 있다는 것을 발견했습니다. 예를 들어, 내가 태어났을 때 개봉한 R 영화는 다음과 같습니다. https://www.filmratings.com/Search?filmYear=1973&filmRating=R&x=20&y=18
저는 브라우저에서 devtools를 열었고 웹 사이트가 데이터를 가져오기 위해 SOAP 기반 웹 서비스를 사용하고 있음을 발견했습니다. https://www.filmratings.com/Filmratings_CARA/WebCaraSearch/Service.asmx
저는 SOAP 웹 서비스를 좋아합니다. 그리고 사랑이라는 말은 정말 정말 싫어한다는 뜻입니다. 하지만 이전에 ( "Working with SOAP in a Node App" ) 그것들을 다뤘고 등급 분포가 수년에 걸쳐 어떻게 변하는지 보는 것이 흥미로울 것이라고 생각했습니다. 나는 웹 서비스가 한 페이지의 데이터와 함께 1년 동안의 총 영화 수 및 등급을 나타내는 값을 반환한다는 것을 알았습니다. 총계는 나에게 충분할 것입니다. 웹사이트를 가지고 놀면서 나는 내가 얻을 수 있는 가장 초기 데이터가 1968년이라는 것을 발견했고, 그것으로 1968년부터 2020년까지의 시청률 합계를 수집하는 스크립트를 만들었습니다.
등급 자체는 수년에 걸쳐 변경되었습니다. 예를 들어 PG-13은 1984년에 추가되었습니다. "GP"와 같은 일부는 제거되었습니다. "X"가 "NC-17"로 변경되었습니다. 내 스크립트의 경우 대부분의 사람들이 인식하는 "일반적인"등급에 초점을 맞추기로 결정했습니다.
저는 1년, 1등급을 얻기 위한 간단한 스크립트로 시작했습니다.
const soap = require('soap');
const apiWSDL = 'https://www.filmratings.com/Filmratings_CARA/WebCaraSearch/Service.asmx?WSDL';
const xml2js = require('xml2js');
(async () => {
let year = 1968;
let rating = 'G';
let client = await soap.createClientAsync(apiWSDL);
let result = await client.GetTitleListByYearRatingFullWithPaginationAsync({
year: 1968,
rating: 'G'
});
let parser = new xml2js.Parser();
let xml = result[0]['GetTitleListByYearRatingFullWithPaginationResult'];
//console.log(xml);
let data = await parser.parseStringPromise(xml);
let total = data.SearchResults.total_response[0];
console.log(`There were ${total} ${rating} movies in ${year}`);
})();
soap
및 xml2js
패키지를 사용하고 있습니다. soap
패키지는 웹 서비스와의 통신을 처리하고 xml2js
는 최종 결과를 구문 분석하는 데 도움이 됩니다. 나는 영화의 이름이 아니라 총계에만 관심이 있다는 것을 기억하십시오. 이 작업을 완료한 다음 스크립트를 좀 더 일반적으로 만들었습니다.const soap = require('soap');
const apiWSDL = 'https://www.filmratings.com/Filmratings_CARA/WebCaraSearch/Service.asmx?WSDL';
const xml2js = require('xml2js');
const parser = new xml2js.Parser();
let client;
const ratings = ['G', 'PG', 'PG-13', 'R', 'NC-17','X'];
const startYear = 1968;
const endYear = 2020;
const fs = require('fs');
const totalResult = [];
(async () => {
for(let year=startYear; year <= endYear; year++) {
let yearResult = { year, ratings:{} };
for(let x=0; x < ratings.length; x++) {
let rating = ratings[x];
let total = await getTotal(year, rating);
console.log(`There were ${total} ${rating} movies in ${year}`);
yearResult.ratings[rating] = parseInt(total,10);
}
totalResult.push(yearResult);
}
fs.writeFileSync('./mparatings.json', JSON.stringify(totalResult), 'utf8');
console.log('Wrote out the data.');
})();
async function getTotal(year, rating) {
if(!client) client = await soap.createClientAsync(apiWSDL);
let result = await client.GetTitleListByYearRatingFullWithPaginationAsync({
year,
rating
});
let xml = result[0]['GetTitleListByYearRatingFullWithPaginationResult'];
//console.log(xml);
let data = await parser.parseStringPromise(xml);
let total = data.SearchResults.total_response[0];
return total;
}
결과를 파일에 기록합니다. 내 생각은 데이터를 한 번만 "스크래핑"하는 것이었습니다. 결과를 가지고 노는 동안 API를 '남용'하고 공격하고 싶지 않았습니다. 다음은 결과가 표시되는 방식의 하위 집합입니다.
[
{
"year": 1968,
"ratings": {
"G": 181,
"PG": 0,
"PG-13": 0,
"R": 49,
"NC-17": 0,
"X": 3
}
},
{
"year": 1969,
"ratings": {
"G": 175,
"PG": 0,
"PG-13": 0,
"R": 77,
"NC-17": 0,
"X": 13
}
},
// more years...
]
시원한. 그래서 이 시점에서 저는 제 모든 데이터를 가지고 있었고 그것을 차트로 작성하기만 하면 되었습니다. 같은 클라이언트 측 차트 작성 솔루션을 연속으로 두 번 이상 사용할 수 없는 것 같아서 ApexCharts이 무료이고 누적 막대 차트를 검색하면 표시되므로 선택했습니다. 나는 코드를 털어 놓을 것이지만 솔직히 나는 대부분 그들의 문서에서 잘라내어 붙여 넣었습니다. 다음은 빈 div인 HTML입니다.
<html>
<head>
</head>
<body>
<div id="chart"></div>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script src="mpa_app.js"></script>
</body>
</html>
그리고 여기 코드가 있습니다. 대부분의 작업은 내가 만든 데이터를 ApexCharts가 원하는 형태로 번역하는 것입니다.
const ratings = ['G', 'PG', 'PG-13', 'R', 'NC-17','X'];
document.addEventListener('DOMContentLoaded', init, false);
async function init() {
let req = await fetch('./mparatings.json');
let data = await req.json();
let allYears = data.map(d => {
return d.year;
});
let series = [];
data.forEach(d => {
for(let rating in d.ratings) {
let existingSeries = series.findIndex(d => {
return d.name === rating;
});
if(existingSeries === -1) {
series.push({name:rating, data:[]});
existingSeries = series.length-1;
}
series[existingSeries].data.push(d.ratings[rating]);
}
});
console.log(series);
let options = {
series,
chart: {
type: 'bar',
height: '100%',
stacked: true,
},
plotOptions: {
bar: {
horizontal: true
},
},
stroke: {
width: 1,
colors: ['#fff']
},
title: {
text: 'MPA Ratings by Years'
},
xaxis: {
categories: allYears
},
yaxis: {
title: {
text: undefined
},
},
fill: {
opacity: 1
},
legend: {
position: 'top',
horizontalAlign: 'left',
offsetX: 40
}
};
let chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
}
결과는 다음과 같습니다.
읽기에 너무 작다는 것을 깨달았습니다. 웹 앱 자체를 여기에 올려 놓았습니다. https://static.raymondcamden.com/demos/mpa/mpa.html 이에 대해 궁금한 점이 있으면 연락주세요!
Reference
이 문제에 관하여(정당한 이유 없이 영화 등급 분포 그래프 작성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/raymondcamden/graphing-movie-rating-distribution-for-no-good-reason-3h0o텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)