[1차 팀프로젝트] '나라장터' 웹스크래핑 하기 (3)
* 아이패드로 이어서 하는 웹스크래핑
-현재 진척사항
1. 2023년 1월 1일부터 15일까지의 입찰공고 페이지 수 확인 완료 (489페이지)
2. 489페이지 까지의 입찰공고 목록 내용 수집 완료
3. 수집내용 데이터 프레임으로 형성 완료
-해야할 사항
1. 컬럼 내용 변경하기 (지울 컬럼 : '공동 수급', '투찰' / 추가할 컬럼 : '재입찰 여부', '추정가격')
2. '재입찰 여부'에 대한 내용 수집할 방법 찾아보기 (셀레니움? 구글 드라이버?)
3. '추정가격'에 대한 내용 수집할 방법 찾아보기 (페이지에 '사업금액' 혹은 '추정가격' 등 표시된 내용이 다 다름)
-실습 환경
1. 시기 : 가족과 함께하는 명절, 설날
2. 장소 : 컴퓨터는 없지만 와이파이는 있는 시골 할머니댁
3. 가진 것 : 노트북은 없지만 대학생때 구매한 아이패드, 이번에 구매한 블루투스 키보드와 마우스
4. 실습 프로그램 : 'Carnets'라는 앱스토어 무료 어플
5. 어려운 점 : 키보드, 마우스가 익숙하지 않음, 이전 실습 내용을 찾아보기 쉽지 않음 (코랩, 주피터노트북 실행 안됨 ㅜ)
13. 현재 컬럼 목록 출력해서 확인하기
* (11번에서 concat으로 데이터 프레임 합친 코드블럭의 다음 블럭에 작성함.)
df.columns
∎ 마지막에서 세번째, 두번째 컬럼을 지워야 한다.
∎ 할줄 몰라서 인덱스 번호를 활용하는 방법 대신 컬럼명을 짚어서 삭제할 예정이다.
∎ 명확한 컬럼명을 알기 위해 .columns 를 활용하여 컬럼명을 출력하였다.
*** 인덱스 번호로 컬럼을 지정하여 지우는 방법은??
14. 컬럼 목록 변경하기 (삭제 및 추가하기)
∎ '공동 수급', '투찰' 컬럼 삭제하기 (.drop 사용하기)
∎ '재입찰 여부', '추정가격' 컬럼 추가하기
df_table = df.drop(['공동 수급', '투찰'], axis=1)
df_table['재입찰 여부'] = 'a'
df_table['추정가격'] = 'b'
df_table.columns
∎ 컬럼이 삭제되고, 새로운 컬럼은 맨 뒤에 추가된 것을 확인할 수 있다.
# 컬럼 변경이 잘 되었는지 확인해보기
df_table
*14* **조원분들의 컬럼 내용 수정 방법**
∎ (강*님) 한 페이지를 수집하는 함수를 만들어서 그 안에서 중복 내용링크 내용 과 컬럼을 삭제함
def get_one_page(page_no):
# 한 페이지 수집
url = get_url(page_no)
response = requests.get(url)
table = pd.read_html(response.text)[0]
soup = bs(response.text)
a_list = soup.select('#resultFrom > div.results > table > tbody > tr > td > div > a')
# (위) '공고번호'와 '공고명'에서 둘 다 링크가 추출됨
# (아래) 같은 게시물에서는 하나의 링크만 취하도록 함 : list comprehension 사용
link_list = [a['href'] for a in a_list if a_list.index(a) % 2 == 0]
# '공동 수급', '투찰' 컬럼 삭제하기
df_one_page = table.iloc[:, :-2].copy()
₩₩₩ iloc[]안에 빈 : 은 무슨 뜻인지? .copy()를 해주는 이유는 무엇인지?₩₩₩
# '업무' 컬럼의 값이 비어있지 않은 항목만 수집하기
df_one_page = df_one_page[~df_one_page['업무'].isnull()]
# '링크' 컬럼 추가하기
df_one_page['링크'] = link_list
return df_one_page
-리스트 컴프리핸션의 형식과 만드는 방법은 어제 희*님과 승*님이 친절히 설명해주셔서 이제 이해 완료 했다.
-하지만 적절한 상황에 적절하게 직접 코드를 작성해서 활용하기에 부족하다는 생각이 들었다.
15. 컬럼 순서 변경하기
- 내용링크 페이지 안에서 정보를 가져오는게 어려워서 일단 할 수 있는 것부터 할 예정이다..
cols = ['분류', '업무', '공고번호-차수', '공고명', '공고기관', '수요기관',
'계약방법', '추정가격', '입력일시 (입찰마감일시)', '재입찰', '내용링크']
table = table[cols]
table
16. '재입찰 여부'에 대한 내용을 찾기
∎ 나라장터의 세부내용 페이지의 형식은 글마다 달라서 일단 여러 게시글을 랜덤으로 들어가 태그경로를 복사해왔다.
* 아이패드는 웹페이지 관리자모드를 볼 수 없어서 어제 컴퓨터로 찾아둔 내용을 활용하였음.
#container > div:nth-child(7) > table > tbody > tr:nth-child(8) > td > div
#container > div:nth-child(7) > table > tbody > tr:nth-child(8) > td > div
#container > div:nth-child(8) > table > tbody > tr:nth-child(9) > td > div
∎ 비슷한 모습을 보인다. ( => 'table > tbody > tr> td > div.tb_inner' 로 축약, div 클래스명 추가)
∎ 출력하면 내용은 이렇게 나올 듯 하다. 어떻게 문자열을 나누면 좋을까?
-모르겠어서 결국 희*님의 코드를 참고하여 작성해보았다.
-하.. 지겨운 오류의 연속.. 어떤 에러인지는 알겠는데 왜 난지는 여전히 모르겠는 지금.
-이번엔 하*님의 코드를 참고해서 작성해보자..
def get_desc(df_link):
a = []
try:
if 'amp;' in df_link:
df_link = df_link.replace('amp;','')
response = requests.get(df_link)
content_html = BeautifulSoup(response.text)
for j in content_html.select('div.section'):
for i in j.select('p.hide'):
if '공고일반' in i.text:
df_table = j.select('table.table_info')
if df_table:
for i in df_table:
for j in i.select('div.tb_inner'):
if '재입찰' in j.text:
m = j.text.strip()
a.append(m.replace("\r",'').replace("\t",'').replace("\n",'').replace(" ",''))
except Exception as e:
#print(f'오류 게시물 링크 : {df_link}, 오류 메시지 : {e}')
a.append('내용 없음')
return a[0]
-오류는 아직 안났지만 소용없다. 왜냐면 무슨 뜻인지 모르기 때문이다.
정말 오류가 나지 않은 건지 보이지 않을 뿐인건지도 모른다. 여기 멈춰있는지 3일째다.
다른 팀원들은 다 찾아내고 결측치 제외하고 데이터 모으고 있는데 나.. 낙오자가 되었따..