반응형
저번 포스팅에서 다중 frame 으로 구성된 HTML에서 HTML 이동하는 방법에 대해 알아봤는데요
이 다음 부분 부터는 설명하기 보다는 따라하기 방식으로 진행하도록 하겠습니다
https://rogios-story.tistory.com/entry/selenium-g2b-Crawling-1-4 (저번 포스팅)
이전 포스팅에서 표시된 용역 버튼을 클릭하는 부분 까지 다루었는데요
<이전 포스팅에서 필요한 부분만 가져옴>
from selenium import webdriver
from selenium.webdriver.common.by import By
import pandas as pd
import requests
from bs4 import BeautifulSoup
# 셀레니움 웹드라이브 열기
driver = webdriver.Chrome()
# 나라장터 URL 접속
url = "https://www.g2b.go.kr/pt/menu/selectSubFrame.do?framesrc=/pt/menu/frameTgong.do?url=https://www.g2b.go.kr:8101/ep/tbid/tbidFwd.do"
driver.get(url)
driver.switch_to.frame('sub') #frame id or name을 이용하여 이동하는 코드 저도 확실하지 않아서 검토 해 보아야함
driver.switch_to.frame('left') #frame id or name을 이용하여 이동하는 코드 저도 확실하지 않아서 검토 해 보아야함
용역버튼 = driver.find_element(By.XPATH, '//*[@id="000019"]/a')
용역버튼.click()
그 다음 공고현황을 클릭해요
driver.find_element(By.XPATH,'//*[@id="000022"]/a').click() # 공고현황 클릭하기
우리가 컨트롤해야 하는 frame는 'main'이라는 것을 알 수 있어요
프레임 이동 등에 대해서 이미 설명 했으니, 자세한 설명 없이 페이지 자동으로 필터링 까지 하는 코드를 추가해볼게요
driver.switch_to.default_content() # 다시 기본 문서로 돌아가기
driver.switch_to.frame('sub') # 다음 frame로 들어가기
driver.switch_to.frame('main') # 입찰정보 검색 frame로 들어가기
driver.find_element(By.XPATH,'//*[@id="setMonth1_3"]').click() #최근 6개월 항목 클릭
# 목록수 100으로 변경하는 코드
from selenium.webdriver.support.select import Select
select_element = driver.find_element(By.CSS_SELECTOR,"#recordCountPerPage")
select = Select(select_element)
select.select_by_value("100")
driver.find_element(By.XPATH,'//*[@id="buttonwrap"]/div/a[1]').click() #검색하기 클릭
# 나중에 쓸 변수 미리 생성
입찰공고목록_합 = pd.DataFrame()
# 첫 번째 검색
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
입찰공고목록_요소 = soup.find('table')
입찰공고목록_table = pd.read_html(str(입찰공고목록_요소))[0]
입찰공고목록_합 = 입찰공고목록_table
# 더 보기 버튼 클릭
driver.find_element(By.CLASS_NAME,'default').click()
# 첫 번째 검색 결과에 2 번째 검색 결과 합치기
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
입찰공고목록_요소 = soup.find('table')
입찰공고목록_table = pd.read_html(str(입찰공고목록_요소))[0]
입찰공고목록_합 = pd.concat([입찰공고목록_합,입찰공고목록_table])
# 더보기 10회 진행하기
i = 0
반복횟수 = 100
while i < 반복횟수:
try:
driver.find_element(By.CLASS_NAME,'default').click()
except:
print('에러 있는듯... 검토 필요')
break
# 첫 번째 검색 결과에 2 번째 검색 결과 합치기
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
입찰공고목록_요소 = soup.find('table')
입찰공고목록_table = pd.read_html(str(입찰공고목록_요소))[0]
입찰공고목록_합 = pd.concat([입찰공고목록_합,입찰공고목록_table])
현재페이지 = driver.find_element(By.XPATH,"//span[@title='현재페이지']").text
print('현재 페이지 번호 : ',현재페이지 )
i = i+1
# 필터링 하기 (공고명에 "건설관리", "실시설계", "기술진단" 이 포함된 내용만 추출)
keywords = ["건설관리", "실시설계", "기술진단"]
입찰공고목록_최종 = 입찰공고목록_합[입찰공고목록_합['공고명'].str.contains('|'.join(keywords))]
위 코드들을 실행하시면 '입찰공고목록_최종' 이라는 변수 안에 필터링된 정보들만 남아있는 모습을 볼 수 있어요
사실 이 방법 보다 더 빠르게 하는 방법이 있는데!!!!
requests 라는 라이브러리를 이용하는 방법입니다!!
다음 포스팅에서는 requests 라는 라이브러리를 이용해서 데이터를 수집하는 방법에 대해 알아볼게요~
#전체코드
# -*- coding: utf-8 -*-
"""
Created on Fri Sep 29 21:12:23 2023
@author: 진연녹
"""
from selenium import webdriver
from selenium.webdriver.common.by import By
import pandas as pd
import requests
from bs4 import BeautifulSoup
#%%
# 셀레니움 웹드라이브 열기
driver = webdriver.Chrome()
# 나라장터 URL
url = "https://www.g2b.go.kr/pt/menu/selectSubFrame.do?framesrc=/pt/menu/frameTgong.do?url=https://www.g2b.go.kr:8101/ep/tbid/tbidFwd.do"
# 나라장터 접속
driver.get(url)
#%%
# 용역 << 요소 탐색
# 용역버튼 = driver.find_element(By.XPATH, '//*[@id="000019"]/a') # <<<<<<<<<<< 코드는 설명을 위해 고의로 에러를 발생시켰으므로 최종 코드에서는 주석처리 함
#%% default 프레임에서 모든 프레임 요소 가져오기
driver.switch_to.default_content() # 기본 문서로 돌아가기 <<<<<<< 한번도 이동하지 않았기에 필요 없지만, 넣어둠
frames = driver.find_elements(By.TAG_NAME,'frame')
# 각 프레임의 name 출력
for frame in frames:
frame_name = frame.get_attribute('name')
print(f'프레임 이름: {frame_name}')
print('프레임 개수 : ',len(frames))
driver.switch_to.frame('sub') #frame id or name을 이용하여 이동하는 코드 저도 확실하지 않아서 검토 해 보아야함
# driver.switch_to.frame(1) #frame 번호로 이동하는 코드 (0,1,2) 순서 이므로 2번 째 프레임으로 이동함
driver.execute_script("return window.frameElement.id;") #현재 프레임 id 갑을 출력하는 코드
driver.switch_to.frame('left') #frame id or name을 이용하여 이동하는 코드 저도 확실하지 않아서 검토 해 보아야함
driver.execute_script("return window.frameElement.name;") #현재 프레임 name 갑을 출력하는 코드
용역버튼 = driver.find_element(By.XPATH, '//*[@id="000019"]/a')
용역버튼.click()
driver.find_element(By.XPATH,'//*[@id="000022"]/a').click() # 공고현황 클릭하기
#%%
driver.switch_to.default_content() # 다시 기본 문서로 돌아가기
driver.switch_to.frame('sub') # 다음 frame로 들어가기
driver.switch_to.frame('main') # 입찰정보 검색 frame로 들어가기
driver.find_element(By.XPATH,'//*[@id="setMonth1_3"]').click() #최근 6개월 항목 클릭
# 목록수 100으로 변경하는 코드
from selenium.webdriver.support.select import Select
select_element = driver.find_element(By.CSS_SELECTOR,"#recordCountPerPage")
select = Select(select_element)
select.select_by_value("100")
driver.find_element(By.XPATH,'//*[@id="buttonwrap"]/div/a[1]').click() #검색하기 클릭
# 나중에 쓸 변수 미리 생성
입찰공고목록_합 = pd.DataFrame()
# 첫 번째 검색
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
입찰공고목록_요소 = soup.find('table')
입찰공고목록_table = pd.read_html(str(입찰공고목록_요소))[0]
입찰공고목록_합 = 입찰공고목록_table
# 더 보기 버튼 클릭
driver.find_element(By.CLASS_NAME,'default').click()
# 첫 번째 검색 결과에 2 번째 검색 결과 합치기
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
입찰공고목록_요소 = soup.find('table')
입찰공고목록_table = pd.read_html(str(입찰공고목록_요소))[0]
입찰공고목록_합 = pd.concat([입찰공고목록_합,입찰공고목록_table])
# 더보기 10회 진행하기
i = 0
반복횟수 = 100
while i < 반복횟수:
try:
driver.find_element(By.CLASS_NAME,'default').click()
except:
print('에러 있는듯... 검토 필요')
break
# 첫 번째 검색 결과에 2 번째 검색 결과 합치기
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
입찰공고목록_요소 = soup.find('table')
입찰공고목록_table = pd.read_html(str(입찰공고목록_요소))[0]
입찰공고목록_합 = pd.concat([입찰공고목록_합,입찰공고목록_table])
현재페이지 = driver.find_element(By.XPATH,"//span[@title='현재페이지']").text
print('현재 페이지 번호 : ',현재페이지 )
i = i+1
# 필터링 하기 (공고명에 "건설관리", "실시설계", "기술진단" 이 포함된 내용만 추출)
keywords = ["건설관리", "실시설계", "기술진단"]
입찰공고목록_최종 = 입찰공고목록_합[입찰공고목록_합['공고명'].str.contains('|'.join(keywords))]
잘 보셨으면 댓글 하나씩만 달아주세요!!!!!!!!!!!!
반응형
'Python(파이썬) > 1. selenium' 카테고리의 다른 글
셀레니움(selenium) 나라장터 데이터 수집하기 4/4 (입찰방법/배정예산/추정가격 등 '용역 입찰공고 상세' 추가하기) (15) | 2023.10.10 |
---|---|
셀레니움(selenium) 나라장터 데이터 수집하기 3/4 (requests 호출 및 데이터 파싱) (4) | 2023.10.05 |
셀레니움(selenium) 나라장터 데이터 수집하기 1/4 (HTML frame 이동) (6) | 2023.09.29 |
셀레니움(selenium) 시작하기 (1) | 2023.09.29 |