1. ANACONDA를 사용하는 이유
2. http method
3. html.parser
beautifulSoup는 웹데이터 수집기라기보다는 parser에 가깝다. html/xml 파일을 읽기 편하게 가공한다.
아래와 같이 html/xml 중 파싱할 대상을 정해줄 수 있다.
bs(response.text, 'html.parser')
4. 데이터베이스권
예시: 네이버 증권 게시판에 글을 쓰면, 데이터베이스권은 네이버에 있으며 저작권은 글쓴이에게 있다.
5.웹스크래핑 시나리오
(1) url 가져오기 - requests 활용
(2) beautifulsoup를 활용해 파싱
(3) 반복문으로 페이지 범주 설정
(4) 데이터프레임으로 반환
6.인코딩
pd.read_html(base_url, encoding = "cp949")
또는, encoding = "utf-8"을 적어주면 됨.
7. a tag parsing
html = bs(response.text)
html.select("td.data-title.aLeft > a")
링크 '<a href =~' 에 해당하는 라인에서 css selector를 카피해와서 넣어줄 수 있다 (child 언급된 부분은 삭제 요망)
def get_one_page(page_no):
120 주요질문의 특정 페이지 목록을 수집
a_link_no = []
for a_tag in a_list:
a_link_no.append(a_tag["href"].split("/")[-1])
table[0]["내용번호"] = a_link_no
7~8 번 코드를 위와 같이 작성하였는데
차이점을 논하자면 a_link_no라는 빈 변수를 선언하고
내용물을 꺼내서 변수 밖에서 설명해주고 다시 넣어준 것이 위의 코드이다.
아래의 코드는 table의 내용번호 컬럼을 생성하면서 a tag와의 관계를 바로 컬럼에 설정해주었다.
#1) page_no 마다 url이 변경되도록 f-string을 사용
base_url = f"https://opengov.seoul.go.kr/civilappeal/list?items_per_page=50&page={page_no}"
#2) requests를 사용해서 요청을 보내고 응답 받기
response = requests.get(base_url)
#3) pd.read_html을 사용해서 table tag로 게시물을 읽어오기
#4) 3번 결과에서 0번 인덱스를 가져와 데이터프레임으로 목록의 내용 만들기
table = pd.read_html(response.text)[0]
#5) html tag를 parsing할 수 있도록 bs 형태로 만들기
pd.read_html(base_url, encoding = "utf-8")
html = bs(reponse.text)
#6) 목록 안에 있는 a_tag를 찾기
a_list = html.select("td.data-title.aLeft > a")
#7) a tag 안에서 string을 분리해서 내용번호만 리스트 형태로 만들기
#8) 4)의 결과에 "내용번호"라는 컬럼을 만들고 a tag의 리스트를 추가
table["내용번호"] = [a_tag["href"].split("/")[-1] for a_tag in a_list]
return table
#1) page_no 마다 url이 변경되도록 f-string을 사용
base_url = f"https://opengov.seoul.go.kr/civilappeal/list?items_per_page=50&page={page_no}"
#2) requests를 사용해서 요청을 보내고 응답 받기
response = requests.get(base_url)
#3) pd.read_html을 사용해서 table tag로 게시물을 읽어오기
#4) 3번 결과에서 0번 인덱스를 가져와 데이터프레임으로 목록의 내용 만들기
table = pd.read_html(response.text)[0]
if table.shape[0] == 0:
return f"{page_no} 페이지를 찾을 수 없습니다."
#5) html tag를 parsing할 수 있도록 bs 형태로 만들기
try:
html = bs(response.text)
#6) 목록 안에 있는 a_tag를 찾기
a_list = html.select("td.data-title.aLeft > a")
#7) a tag 안에서 string을 분리해서 내용번호만 리스트 형태로 만들기
#8) 4)의 결과에 "내용번호"라는 컬럼을 만들고 a tag의 리스트를 추가
table["내용번호"] = [a_tag["href"].split("/")[-1] for a_tag in a_list]
except:
# 중간에 오류가 발생해도 계속 코드를 진행해야 하는 경우, 에러메세지를 출력하게 해준다
return f"{page_no}페이지를 찾을 수 없습니다."
return table
조건을 걸어준 try문과 except문을 기억하자 - 예외조건을 제외하고는 모두 try에 넣어준다는 의미
# time.sleep을 통해 일정 간격 쉬었다가 가져옵니다.
# 게시물이 없으면 멈춥니다.
page_no = 1
table_list = []
while True:
df_temp = get_one_page(page_no)
if type(df_temp) == str:
print("수집이 완료되었습니다.")
break
print(page_no, end=",")
table_list.append(df_temp)
page_no +=1
time.sleep(0.01)
여기서는 df_temp와 time.sleep에 유의할 것!
# 내용 페이지의 주소를 url 변수에 담아줍니다.
# 웹페이지의 결과를 받아옵니다.
# BeautifulSoup을 통해 lxml로 파싱해 올 수 있도록 합니다.
# html 태그에서 "div.line-all"의 0번째 값을 선택(select)하여 text를 확인합니다.
url = "https://opengov.seoul.go.kr/civilappeal/view/?nid=23194045"
print(url)
response =requests.get(url)
html = bs(response.text)
# content
contetnt = html.select("div.view-content.view-content-article > div > div.line-all")[0].get_text()
table[[0,1]].set_index(0).T
t는 행과 열을 바꿔주는 기능을 한다. 전치 행렬을 의미 - transform
table[[a,3]].set_index(a).T
a의 숫자를 맞춰줘야 결과가 나온다. a는 어떤 컬럼을 인덱스로 만들 것인지 지정해주는 값이다.
pd.concat([tb01, tb02], axis=1)
표1과 표2의 값을 합침 - 기준은 axis
tb01.columns, tb02.columns