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

Pull/74 #78

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0940814
[feat] 국회의원 다양성 지수 계산
pingpingy1 Nov 27, 2023
c227a71
[fix] 비례대표 국회의원까지 함께 계산에 추가
pingpingy1 Nov 28, 2023
54a8142
[feat] 역대 성별 조성 DB에 저장
pingpingy1 Nov 28, 2023
e973b57
[feat] 역대 정당 조성 DB에 저장
pingpingy1 Nov 28, 2023
084bb29
[fix] 비례대표 의원도 다양성 지수 계산에 추가
pingpingy1 Nov 29, 2023
30f4125
[feat] 국회의원 연령 통계 계산, DB에 저장
pingpingy1 Nov 29, 2023
8fd08ed
feat: send webhooks to slack app when scraping
keonly Nov 25, 2023
550ce1f
feat: add option to disable webhook
keonly Nov 27, 2023
fdba9d1
feat(add) : all datas
happycastle114 Nov 27, 2023
9affdfe
[analysis] MongoDB에서 데이터 불러오도록 작성. 추후 mongoDB councilor에 year 추가되면 테스…
Re-st Nov 27, 2023
46564ed
Formatted with black
Re-st Nov 27, 2023
9e7a0a3
feat(add) national council global
happycastle114 Nov 27, 2023
f4b0c2d
Formatted with black
happycastle114 Nov 27, 2023
3bc3a24
feat(add) global candidate
happycastle114 Nov 27, 2023
bb521a4
Formatted with black
happycastle114 Nov 27, 2023
342a9ff
feat: add year field to entries
keonly Nov 27, 2023
afb67ef
fix: change local and metro id to snake_case
keonly Nov 27, 2023
0029824
fix: change local and metro id to camelCase
keonly Nov 27, 2023
e28d447
[scrap] 남은것 205, 207, 209, 211, 221, 223, 225
Re-st Nov 27, 2023
240d443
Formatted with black
Re-st Nov 27, 2023
0d84b39
fix: typo in secret key
keonly Nov 28, 2023
dcdd208
feat: add manual update to mongo from local json
keonly Nov 28, 2023
6b87c24
feat: match command line options to scraper's
keonly Nov 28, 2023
04ab312
fix: update error message for not implemented sgTypeCode
keonly Nov 28, 2023
b455a14
fix: wrong reference from parsed arguments
keonly Nov 28, 2023
cc9a1c3
Formatted with black
keonly Nov 28, 2023
f641cbd
fix: year update
happycastle114 Nov 29, 2023
9064859
Add: 비례대표 대응
happycastle114 Nov 30, 2023
437711c
[scrap] 205
Re-st Nov 30, 2023
b7e4dc4
Formatted with black
Re-st Nov 30, 2023
0f3a208
[analysis] 국회 age_hist 고침
Re-st Nov 30, 2023
7909495
Formatted with black
Re-st Nov 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# required environment variables
MONGO_CONNECTION_URI=mongodb://localhost:27017
OPEN_DATA_SERICE_KEY=some_key
OPEN_DATA_SERVICE_KEY=some_key
MONGO_DATABASE=council
3 changes: 3 additions & 0 deletions API/MongoDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Councilor:
job: str
eduId: int
edu: str
year: str

@classmethod
def from_dict(cls, data: dict):
Expand All @@ -31,6 +32,7 @@ def from_dict(cls, data: dict):
job=data.get("job"),
eduId=int(data.get("eduId")),
edu=data.get("edu"),
year=data.get("year"),
)

def to_dict(self):
Expand All @@ -47,4 +49,5 @@ def to_dict(self):
"job": self.job,
"eduId": self.eduId,
"edu": self.edu,
"year": self.year,
}
3 changes: 2 additions & 1 deletion API/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@
"8": CouncilType.METROPOLITAN_COUNCIL,
"9": CouncilType.LOCAL_COUNCIL,
}

CANDIDATE_TYPECODE_TYPE = {
"2": CouncilType.NATIONAL_COUNCIL_CAND,
# "3": CouncilType.METRO_LEADER_CAND,
# "4": CouncilType.LOCAL_LEADER_CAND,
"5": CouncilType.METROPOLITAN_COUNCIL_CAND,
"6": CouncilType.LOCAL_COUNCIL_CAND,
"7": CouncilType.NATIONAL_COUNCIL_CAND,
"7": CouncilType.NATIONAL_COUNCIL_GLOBAL_CAND,
"8": CouncilType.METROPOLITAN_COUNCIL_CAND,
"9": CouncilType.LOCAL_COUNCIL_CAND,
}
42 changes: 25 additions & 17 deletions API/candidate.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,36 @@ def fetch_all_data(
parser.add_argument(
"--drop-columns",
type=str,
default="num,huboid,hanjaName,status",
default="num,huboid,hanjaName,status,gihoSangse",
help="제거할 열 이름을 ','로 구분하여 입력하세요",
)
parser.add_argument(
"--save-method",
type=str,
# TODO: Add MongoDB support
# choices=["excel", "mongo"],
choices=["excel"],
default="excel",
help="데이터 저장 방식: 'excel' (현재는 excel만 지원)",
"-m", "--update-mongo", help="API 요청 결과를 MongoDB에 업데이트", action="store_true"
)
parser.add_argument(
"-o", "--output-store", help="API 요청 결과를 로컬에 저장", action="store_true"
)
parser.add_argument("--output-path", help="API 요청 결과 저장 경로", default="output")

args = vars(parser.parse_args())
print(args)
sgIds = args.get("sgIds").split(",")
if args.get("drop_columns"):
drop_columns = args.get("drop_columns").split(",")
else:
drop_columns = []
print(drop_columns)

data_list = fetch_all_data(
sgIds, args.get("sgTypecodes"), drop_columns=drop_columns
)

args = parser.parse_args()
sgIds = args.sgIds.split(",")
drop_columns = args.drop_columns.split(",") if args.drop_columns else []

data_list = fetch_all_data(sgIds, args.sgTypecodes, drop_columns=drop_columns)
for sgTypecode in args.sgTypecodes.split(","):
for sgTypecode in args.get("sgTypecodes").split(","):
if sgTypecode not in SG_TYPECODE:
raise ValueError(f"Invalid sgTypecode: {sgTypecode}")
if args.save_method == "excel":
save_to_excel(data_list, sgTypecode, is_elected=False)
elif args.save_method == "mongo":

if args.get("update_mongo"):
save_to_mongo(data_list, sgTypecode, CANDIDATE_TYPECODE_TYPE[sgTypecode])

if args.get("output_store"):
save_to_excel(data_list, sgTypecode, is_elected=False)
35 changes: 22 additions & 13 deletions API/elected.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def fetch_data(
data_list = []
for item in root.findall(".//item"):
data_entry = {child.tag: child.text for child in item}
data_entry["year"] = sgId[:4]

for column in drop_columns:
data_entry.pop(column)
Expand Down Expand Up @@ -72,22 +73,30 @@ def fetch_all_data(
help="제거할 열 이름을 ','로 구분하여 입력하세요",
)
parser.add_argument(
"--save-method",
type=str,
choices=["excel", "mongo"],
default="excel",
help="데이터 저장 방식: 'excel', 'mongo'",
"-m", "--update-mongo", help="API 요청 결과를 MongoDB에 업데이트", action="store_true"
)
parser.add_argument(
"-o", "--output-store", help="API 요청 결과를 로컬에 저장", action="store_true"
)
parser.add_argument("--output-path", help="API 요청 결과 저장 경로", default="output")

args = parser.parse_args()
sgIds = args.sgIds.split(",")
drop_columns = args.drop_columns.split(",") if args.drop_columns else []
args = vars(parser.parse_args())
sgIds = args.get("sgIds").split(",")
if args.get("drop_columns"):
drop_columns = args.get("drop_columns").split(",")
else:
drop_columns = []

data_list = fetch_all_data(
sgIds, args.get("sgTypecodes"), drop_columns=drop_columns
)

data_list = fetch_all_data(sgIds, args.sgTypecodes, drop_columns=drop_columns)
for sgTypecode in args.sgTypecodes.split(","):
for sgTypecode in args.get("sgTypecodes").split(","):
if sgTypecode not in SG_TYPECODE:
raise ValueError(f"Invalid sgTypecode: {sgTypecode}")
if args.save_method == "excel":
save_to_excel(data_list, sgTypecode, is_elected=True)
elif args.save_method == "mongo":

if args.get("update_mongo"):
save_to_mongo(data_list, sgTypecode, ELECTED_TYPECODE_TYPE[sgTypecode])

if args.get("output_store"):
save_to_excel(data_list, sgTypecode, is_elected=True)
67 changes: 17 additions & 50 deletions API/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,17 @@ def save_to_mongo(data: List[dict], sgTypecode: str, where: str) -> None:
main_collection = db[where]

# TODO: Support other types of councils
if sgTypecode in ["6", "9"]:
if sgTypecode in ["8", "5", "2", "6", "9"]:
for entry in data:
if entry["wiwName"] == None:
print(entry)
entry["wiwName"] = change_local_name(entry["sdName"], entry["wiwName"])
district_id = get_district_id(entry["sdName"], entry["wiwName"])

if district_id:
main_collection.update_one(
{
"year": entry["year"],
"name": entry["name"],
"localId": district_id["localId"],
"metroId": district_id["metroId"],
Expand All @@ -60,34 +63,21 @@ def save_to_mongo(data: List[dict], sgTypecode: str, where: str) -> None:
print(
f"Warning: '{entry['sdName']} {entry['wiwName']}'에 해당하는 지역 ID가 존재하지 않습니다."
)
elif sgTypecode in ["5", "8"]:
main_collection = db["metro_councilor"]
elif sgTypecode in ["7"]:
for entry in data:
entry["wiwName"] = change_local_name(entry["sdName"], entry["wiwName"])
district_id = get_district_id(entry["sdName"], entry["wiwName"])

if not district_id:
print(
f"Warning: '{entry['sdName']} {entry['wiwName']}'에 해당하는 지역 ID가 존재하지 않습니다."
)
continue

if district_id:
main_collection.update_one(
{
"name": entry["name"],
"local_id": district_id["local_id"],
"metro_id": district_id["metro_id"],
},
{"$set": Councilor.from_dict(entry).to_dict()},
upsert=True,
)
else:
print(
f"Warning: '{entry['sdName']} {entry['wiwName']}'에 해당하는 지역 ID가 존재하지 않습니다."
)
entry["wiwName"] = "전국"
main_collection.update_one(
{
"year": entry["year"],
"name": entry["name"],
"localId": 0,
"metroId": 0,
},
{"$set": Councilor.from_dict(entry).to_dict()},
upsert=True,
)
else:
raise NotImplementedError("현재 구시군의회의원(6) 및 기초의원비례대표(9)만 구현되어 있습니다.")
raise NotImplementedError(f"아직 구현되지 않은 sgTypecode: {sgTypecode}")

print(f"데이터를 성공적으로 MongoDB '{main_collection.name}' 컬렉션에 저장하였습니다.")

Expand Down Expand Up @@ -124,29 +114,6 @@ def getLocalMetroMap() -> Dict[str, str]:
}


def getLocalMetroMap() -> Dict[str, str]:
db = client["district"]
result = db["local_district"].aggregate(
[
{
"$project": {
"localId": 1,
"metroId": 1,
"sdName": 1,
"wiwName": 1,
}
},
]
)
return {
(item["sdName"], item["wiwName"]): {
"local_id": item["localId"],
"metro_id": item["metroId"],
}
for item in result
}


def change_local_name(sdName, wiwName):
"""
1. 만약 '시' 와 '구'가 모두 wiwName에 있다면, '시' 까지만 쓰기
Expand Down
44 changes: 24 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# 다양성 평가 리포트 웹사이트 - 뉴웨이즈

<!-- # 깃헙은 최종일에 제출 필요!
- 팀별 GitHub repository 링크 및 발표 자료 Slack으로 제출
- GitHub 포함 사항
Expand All @@ -9,44 +10,47 @@
- 설치 및 실행 과정 설명
- 팀 및 팀원 소개
- (선택 사항) 데모 영상 -->

## 프로젝트 개요
프로젝트 이름 다양성 평가 리포트 웹사이트 - 뉴웨이즈
기간 23 가을-겨울

프로젝트 이름 다양성 평가 리포트 웹사이트 - 뉴웨이즈
기간 23 가을-겨울

## 설치 및 실행 과정

1. 파이썬 가상환경 생성
- 아래 명령을 실행하여 파이썬 가상환경을 생성합니다.
```bash
cd ~ && virtualenv newways --python=3.10
```
- 아래 명령을 실행하여 파이썬 가상환경을 생성합니다.
```bash
cd ~ && virtualenv newways --python=3.10
```
2. 가상환경 활성화
- 아래 명령을 실행하여 가상환경을 활성화합니다.
```bash
source ~/newways/bin/activate
```
- 아래 명령을 실행하여 가상환경을 활성화합니다.
```bash
source ~/newways/bin/activate
```
3. 레포지토리 클론
- 아래 명령을 실행하여 레포지토리를 클론합니다.
```bash
git clone https://github.com/NewWays-TechForImpactKAIST/main
```
```
4. 필요한 패키지 설치
- requirements.txt에 명시된 패키지를 설치합니다.
```bash
pip install -r requirements.txt
```
```
5. 환경 변수 설정
- `.env.example` 파일을 복사하여 `.env` 파일을 생성합니다.
```bash
cp .env.example .env
```
- `.env` 파일을 열어 환경 변수의 값을 필요에 따라 바꾸어줍니다.
```
- `.env` 파일을 열어 환경 변수의 값을 필요에 따라 바꾸어줍니다.
6. 예제 코드 실행
- 이 프로젝트는 여러 개의 파이썬 패키지로 구성되어 있습니다.
- 각각의 패키지는 독립적으로 실행할 수 있습니다. 단, 실행 시 python -m 옵션(module을 의미)을 사용해야 합니다.
- 크롤링 및 데이터베이스 저장 예제 코드를 실행하려면, 아래 명령을 실행합니다.
```bash
# scrap/local_councils/seoul/junggu.py 파일을 실행합니다.
python -m scrap.local_councils.seoul.junggu
# scrap/examples/database.py 파일을 실행합니다.
python -m scrap.examples.database
```
```bash
# scrap/local_councils/seoul/junggu.py 파일을 실행합니다.
python -m scrap.local_councils.seoul.junggu
# scrap/examples/database.py 파일을 실행합니다.
python -m scrap.examples.database
```
10 changes: 5 additions & 5 deletions analysis/age/hist_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def insert_data_to_mongo(
)


def cluster(df_original, n_clst, basedic):
def cluster(df_original, n_clst, basedic, clean_flag=True):
"""구역별 그룹을 만듭니다.
df_original: 데이터프레임
n_clst: 그룹 수
Expand All @@ -194,11 +194,11 @@ def cluster(df_original, n_clst, basedic):
histcoll = statdb["age_hist"]
statcoll = statdb["age_stat"] # method = "equal"에서 써 줄 통계.
# 기존 histogram 정보는 삭제 (나이별로 넣는 것이기 때문에 찌꺼기값 존재가능)
histcoll.delete_many(basedic.__dict__)
if basedic.method == "equal":
statcoll.delete_many(basedic.__dict__)
if clean_flag:
histcoll.delete_many(basedic.__dict__)
if basedic.method == "equal":
statcoll.delete_many(basedic.__dict__)
# 연도별로 데이터 찾아서 넣기!
df_original["year"] = df_original["sgId"] // 10000
df_original = df_original[df_original["year"].isin([2010, 2014, 2018, 2022])]
years = df_original["year"].unique()
for year in years:
Expand Down
Loading