기계학습으로 봉사활동 추천시스템를 구상하고 있다.
그래서 가장 기초가 되는 데이터 모으기부터 시작
1
2
3
4
5
6
|
from selenium import webdriver
from bs4 import BeautifulSoup
import pandas as pd
import time
import re
import csv
|
cs |
필요한 라이브러리는 요정도.
selenium으로 mobile 버전에서 더보기를 눌러주고 각 내용을 가져오려고 한다.
사실 selenium을 안쓰고 requests로만 구현을 했었는데 pc버전에서 왜이리 값을 다 못받아 오는지 모르겠다.
삽질 끝에 mobile 버전이 조금 더 단순한 형태기도해서 사용한다.
1
2
|
driver = webdriver.Chrome()
driver.implicitly_wait(3)
|
cs |
webdriver로 크롬 열어주고, 카페 게시글을 읽으려면 로그인이 유지되어야 한다.
1
2
3
4
5
6
7
|
# 로그인 전용 화면
driver.get('https://nid.naver.com/nidlogin.login?svctype=262144&url=http://m.naver.com/aside/')
# 아이디와 비밀번호 입력
driver.find_element_by_name('id').send_keys('tjdcks9243')
driver.find_element_by_name('pw').send_keys('********')
# 로그인 버튼 클릭
driver.find_element_by_css_selector('#frmNIDLogin > fieldset > input').click()
|
cs |
f12 눌러서 소스코드를 확인해보면
아이디 값의 input name는 id, 비밀번호 값의 input name은 pw이다. 자동화로 잘 넣어줄 것이고
로그인 버튼의 path를 가져오면 저렇게 되므로 눌러주면 로그인 완료
pc버전에서 진행할 때는 session을 이용해서 쭉 유지시켜주면 끝인데
mobile 버전은 로그인 때 타이밍 안맞아서도 가끔나고 좀 귀찮아서 그냥 수동으로 로그인하고 카페들어감ㅋ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
base_url = 'https://m.cafe.naver.com/ArticleList.nhn?search.clubid=15754634&search.menuid=33'
test_list = []
driver.get(base_url)
# iframe으로 프레임 전환
# driver.switch_to_frame('cafe_main')
for page_num in range(1,50):
# 더보기 버튼 50번 클릭
driver.find_element_by_xpath('//*[@id="btnNextList"]/a').click()
# 로딩 시간이 있으므로 타이밍 맞추기 위해 sleep(0.5)
time.sleep(0.5)
# # href 속성을 찾아 url을 리스트로 저장한다.
article_list = driver.find_elements_by_css_selector('li.board_box a.txt_area')
article_urls = [ i.get_attribute('href') for i in article_list ]
for link in article_urls:
test_list.append(link)
|
cs |
base_url은 스펙업의 국내 봉사 url
link들을 저장할 변수 test_list를 만들고 driver.get으로 접속한다.
pc버전을 크롤링 할 때는 네이버 카페가 iframe 형식이라서 꼭 프레임 전환을 해야 먹는다고 함
selenium의 좋은점은 xpath를 그냥 가져올 수 있다는 것이다.
귀찮게 tag들 따져가며 하는 것 보다 우클릭 -> copy xpath 하면 끝이라.. 좋다.
무튼 더보기로 50번 클릭을 해줘서 1000개 정도 띄워놓고 각 게시글의 url을 긁어와서 test_list에 저장한다.
1
2
|
len(test_list)
# 1000
|
cs |
1
2
3
4
5
6
7
8
9
|
total_list=['제목','작성 날짜','주최사','활동내용','모집 기간','모집 인원','모집 대상',
'참가 비용 유/무','우대 사항','활동 지역','활동 기간']
f = open('mobile_spec_up3.csv', 'w', encoding='ansi', newline='')
wr = csv.writer(f)
wr.writerow([total_list[0], total_list[1], total_list[2],total_list[3],total_list[4],total_list[5],
total_list[6],total_list[7],total_list[8],total_list[9],total_list[10]])
f.close()
|
cs |
저장될 csv의 제목을 따로 넣어주고 엑셀에서 바로 읽기 쉽게 ansi로 encoding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
total_lists = []
for i in range(len(test_list)):
driver.get(test_list[i])
html = BeautifulSoup(driver.page_source , 'html.parser')
content_tags = html.select('#postContent')
# 본문 내용을 줄바꿈 기준으로 다 붙이기
# 각 항목마다 쓸데없이 \xa0▷ 요게 붙여져
content = ' '.join([tags.get_text().replace("\xa0","").replace("▷","") for tags in content_tags])
# 제목가져오기
titles = html.select("h2.tit")
# 날짜가져오기
dates = html.select("span.date.font_l")
# 전체 개수를 알아보기 위해 t 변수 저장
# find_location : 크롤링한 content를 처리해주기 위해서 만듬
t = find_location('mobile_spec_up3.csv',titles, dates, content)
total_lists.append(t)
|
cs |
위에서 링크들을 저장한 test_list에서 한개씩 접속해서 내용들을 싹 긁는다
content를 가져와서 join으로 다 묶어버리고 반복되서 나오는 쓸데없는 문자처리좀 해주면 깔끔스
저장한 content, title, date를 find_location 함수로 인자로 넘겨버린다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
def find_location(name,title,dates,test):
fl=[]
temp_list = []
new_list= []
############################################
#
# 여기에 조건을 주자.
#
############################################
# 주최사 / 활동명 -> activity_name + 9
activity_name = test.find("주최사")
# 활동내용 -> activity_content + 4
activity_content = test.find("활동내용")
# 모집 기간 -> recruit_date + 5
recruit_date = test.find("모집 기간")
# 모집 인원 + 5
recruit_people = test.find("모집 인원")
# 모집 대상 + 16
recruit_target = test.find("모집 대상(+졸업생 가능여부)")
# 참가 비용 유/무 + 9
fee = test.find("참가 비용 유/무")
# 우대 사항 + 5
preferential_treatment = test.find("우대 사항")
# 활동 지역 + 5
activity_nation = test.find("활동 지역")
# 활동 기간 + 5
activity_period = test.find("활동 기간")
# 활동 혜택 + 5
activity_bonus = test.find("활동 혜택")
#저장된 제목 값이 없으면, 저장 안 함
if len(title) != 0:
# 제목 처리
titles = title[0].get_text()
# title_sub = titles.find("(")
# if title_sub != -1:
# titles = titles[:title_sub]
dates = dates[0].get_text()
dates_ = re.sub(r"[.]","",dates)
dates = dates_[:8]
# find의 값이 없으면, -1을 리턴한다.
# 활동 이름이 없으면,
if activity_name != -1:
fl.append(activity_name)
fl.append(activity_content)
fl.append(recruit_date)
fl.append(recruit_people)
fl.append(recruit_target)
fl.append(fee)
fl.append(preferential_treatment)
fl.append(activity_nation)
fl.append(activity_period)
fl.append(activity_bonus)
a1 = re.sub(r"[-]","",test[fl[0]+9:fl[1]].strip())
a2 = re.sub(r"[-]","",test[fl[1]+4:fl[2]].strip())
a3 = re.sub(r"[-]","",test[fl[2]+5:fl[3]].strip())
a4 = re.sub(r"[-]","",test[fl[3]+5:fl[4]].strip())
a5 = re.sub(r"[-]","",test[fl[4]+16:fl[5]].strip())
a6 = re.sub(r"[-]","",test[fl[5]+9:fl[6]].strip())
a7 = re.sub(r"[-]","",test[fl[6]+5:fl[7]].strip())
a8 = re.sub(r"[-]","",test[fl[7]+5:fl[8]].strip())
a9 = re.sub(r"[-]","",test[fl[8]+5:fl[9]].strip())
if a1.find(',') is not -1:
a1 = a1[ :a1.find(',')].strip()
if a1.find('/') is not -1:
a1 = a1[ :a1.find('/')].strip()
# a1_sub = a1.find("(")
# if a1_sub != -1:
# a1 = a1[:a1_sub]
# temp_list=[titles,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13]
temp_list=[titles,dates,a1,a2,a3,a4,a5,a6,a7,a8,a9]
try:
f = open(name, 'a+', encoding='ansi',newline='')
wr = csv.writer(f)
wr.writerow(temp_list)
f.close()
except:
pass
return temp_list
|
cs |
content를 join으로 붙여놔서 형식이 이렇게 나올 것이다.
====================================
주최사 / 활동명한국 청소년 문화진흥협회, 토론 공교육 문화운동본부 대학생 연합 토론교육봉사 단체 "대학생 풍뎅이 봉사단 7기"활동내용-서울지역 3개 지부(수유, 홍대, 건대) 지역아동센터에서 토론교육 봉사를 실시(주 1회)-전국토론대회에서 심사위원이나 토론 진행을 맡는 퍼실리테이터로 위촉되어 활동(매 학기 1회)-프로그램 제작팀, 기획팀, 인프라 구축팀에 소속되어 팀 활동 진행-매월 마지막 주 토요일 총회 진행-토론활동지도사 3급 자격증 취득을 위한 자격증 교육 이수모집 기간7월 16일~8월 10일모집 인원00명모집 대상토론을 좋아하고 교육을 사랑하는 휴학생, 재학생.........
=====================================
그래서 주최사가 나오는 자릿수를 찾고, 그 다음 활동 내용이 등장하는 자릿수를 찾아서 그 사이의 값은 주최사구나 라고 판단하여 처리를 함
그 중에 주최사 / 활동명 중에서 필요한 컬럼은 주최사기 때문에 / 나 , 를 기준으로 앞에 거를 주최사로 생각하여 a1에 다시 저장한다.
정규식과 요로코롬 작업을 해주고 아까 만들었던 csv에 a+ 옵션을 줘서 덮어쓰기로 싹 쓰면 끝
temp_list를 return 하는건 몇 개 들어갔는지 확인하기 위함이므로 return을 안해도 된다.
결과물
카페에서 개인이 글을 쓰다보니 형식에 맞지 않는 거는 어쩔 수 없다.
이미지만 있는 것은 아예 배제
이제는 자유분방하게 작성하신 모집 기간이랑 활동 기간을 잘.......처리할 일만 남았다.
'프로젝트 > 봉사왕심봉사' 카테고리의 다른 글
[naver/google geocoding] 위도/경도 값 구하기 (0) | 2018.09.03 |
---|