일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 신종코로나
- 확진자수
- sharonchoi
- 우한코로나바이러스
- 어서와한국은처음이지
- 우한 코로나
- Bolton
- 전염병
- everybody wants you
- wuhan
- 조현병
- 미중
- 우한
- 정은경 본부장님
- cnn
- 최성재
- 진짜영웅
- parasite
- red hearse
- 코로나
- 봉준호감독통역사
- 필리핀사망
- 코로나19
- 코로나바이러스
- 봉준호감독통역
- 웨일즈
- 우한코로나
- 치앙마이
- 창궐
- 중국외교부
- Today
- Total
오지's blog
진료행위정보서비스 크롤러 개발중 해결한 selenium을 이용한 년월 선택문제 본문
공공데이터포털 내 건강보험심사평가원에서 제공하는 진료행위정보서비스 API가 있다 그러나 2013년 이후는 모두 0이 나오길래 이상하여 직접 기관에 전화하여 확인하니 애석하게도 2013년 이후의 데이터는 안넣고 있고 기약은 없지만 내년즈음 서비스를 개편하여 제공하려고 계획은 하고 있다고 한다. 그걸 세월아 내월아 기다릴수 없어 방법을 찾아본 결과 직접 심평원에서 제공하고 있는 보건의료빅데이터개방시스템에서 직접 엑셀파일을 다운로드 하는 크롤러를 개발하는 방법밖에 없었다. 그리고 나서 엑셀파일을 직접 데이터베이스에 넣는 방식으로 데이터 구축을 해야 했다.
그러나 나와 같은 문제가 발생하여 어떤 훌륭한 분이 크롤러를 개발해 두었다. 문제는 이 크롤러가 개발된지 오래되어 deprecate된것이 있고 시작 날짜는 지정되는데 끝날짜는 지정되지 않는 문제가 있었다.
그래서 끝날짜를 지정하도록 수정하고 싶었는데 제대로 되지 않았다. 다음은 그 문제의 코드이다.
### 검색 시작 날짜 선택
# ext-gen1645 > table > tbody > tr > td > div:nth-child(4) > div > input:nth-child(2)
date_to = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR,"#ext-gen1645 > table > tbody > tr > td > div:nth-child(4) > div > input:nth-child(2)")))
date_to.click()
# ## 정규표현식으로 id 찾기 (엘리먼트의 id값이 날자를 기준으로 페이지 로드 마다 계속해서 바뀜)
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
id_css = re.search(r'monthpicker_\d+', str(soup))
## 달력에서 년도 선택
year_css = '#'+ id_css.group() +' > div > select > option:nth-child(9)'
year = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, year_css)))
year.click()
## 달력에서 월 선택
month_css = '#' + id_css.group() + ' > table > tbody > tr:nth-child(3) > td:nth-child(2)'
month = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, month_css)))
month.click()
### 검색 끝 날짜 선택
# ext-gen1645 > table > tbody > tr > td > div:nth-child(4) > div > input:nth-child(4)
date_from = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR,"#ext-gen1645 > table > tbody > tr > td > div:nth-child(4) > div > input:nth-child(4)")))
date_from.click()
## 정규표현식으로 id 찾기 (엘리먼트의 id값이 날자를 기준으로 페이지 로드 마다 계속해서 바뀜)
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
id_css_from = re.search(r'monthpicker_\d+', str(soup))
# ## 달력에서 년도 선택
# # monthpicker_0009401117271277718 > div > select > option:nth-child(10)
year_css = '#'+ id_css_from.group() +' > div > select > option:nth-child(10)'
# 아래부분에서 exception발생
year = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, year_css)))
year.click()
## 달력에서 월 선택
month_css = '#' + id_css_from.group() + ' > table > tbody > tr:nth-child(3) > td:nth-child(2)'
month = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, month_css)))
month.click()
## 조회 버튼
driver.implicitly_wait(120)
search_btn = driver.find_element_by_class_name("dt-btn-search")
driver.execute_script("arguments[0].click();", search_btn)
driver.implicitly_wait(10)
문제는 끝년도 선택하는데 웨이팅과정에서 exception이 발생했다.
# 아래부분에서 exception발생
year = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, year_css)))
year_css가 첫번째 달력을 가리키고 있는데 두번째 달력의 년도를 클릭하려고 하니 에러가 발생한 것이였다.
이에, bs4를 통해서 monthpicker_ 로 시작하는 id를 찾고 두가지가 있으니 배열과 dict형을 통해서 monthpicker_ 뒤의 숫자값을 get하는 과정을 통해 해결하였다.
다음은 문제를 해결하여 끝년도와 월이 선택되는 코드이다.
### 검색 시작 날짜 선택
# ext-gen1645 > table > tbody > tr > td > div:nth-child(4) > div > input:nth-child(2)
date_to = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR,"#ext-gen1645 > table > tbody > tr > td > div:nth-child(4) > div > input:nth-child(2)")))
date_to.click()
# ## 정규표현식으로 id 찾기 (엘리먼트의 id값이 날자를 기준으로 페이지 로드 마다 계속해서 바뀜)
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
mpid = soup.find_all(id=lambda x: x and x.startswith('monthpicker_'))
print(mpid[0].attrs['id'])
print(mpid[1].attrs['id'])
## 달력에서 년도 선택
year_css = '#'+ mpid[0].attrs['id'] +' > div > select > option:nth-child(6)'
year = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, year_css)))
year.click()
## 달력에서 월 선택
month_css = '#' + mpid[0].attrs['id'] + ' > table > tbody > tr:nth-child(3) > td:nth-child(2)'
month = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, month_css)))
month.click()
### 검색 끝 날짜 선택
# ext-gen1645 > table > tbody > tr > td > div:nth-child(4) > div > input:nth-child(4)
date_from = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR,"#ext-gen1645 > table > tbody > tr > td > div:nth-child(4) > div > input:nth-child(4)")))
date_from.click()
# ## 달력에서 년도 선택
# # monthpicker_0009401117271277718 > div > select > option:nth-child(10)
year_css = '#'+ mpid[1].attrs['id'] +' > div > select > option:nth-child(10)'
year = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, year_css)))
year.click()
## 달력에서 월 선택
month_css = '#' + mpid[1].attrs['id'] + ' > table > tbody > tr:nth-child(3) > td:nth-child(2)'
month = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, month_css)))
month.click()
## 조회 버튼
driver.implicitly_wait(120)
search_btn = driver.find_element_by_class_name("dt-btn-search")
driver.execute_script("arguments[0].click();", search_btn)
위코드의 핵심은 monthpicker_ 로 시작하는 id값을 찾는 과정으로 다음과 같다.
mpid = soup.find_all(id=lambda x: x and x.startswith('monthpicker_'))
이를 통해 css든 xpath든 각 요소에 접근할수 있다.
refereneces
https://github.com/code-sonya/crawling
https://stackoverflow.com/questions/42195472/using-regular-expression-in-find-all-of-beautifulsoup
'개발노트 > Python' 카테고리의 다른 글
WARNING - State of this instance has been externally set to None. Taking the poison pill. (0) | 2021.09.07 |
---|---|
freeCodeCamp.org의 python immediate 연습 (0) | 2021.08.29 |
pymysql.err.Error: Already closed 에러발생 해결과정 (0) | 2021.04.09 |
python에서 super()와 부모클래스이름(parent class name)의 차이점 (0) | 2021.04.07 |
folium popup size 수정하는 방법 (0) | 2021.03.21 |