Day 14
url알아보기
네트워크 > XHR/JS/Doc > Headers 에서 원하는 URL을 찾을 수 있다
pd.read_html(url) #url의 table정보를 읽어온다
pd.read_html(url, encoding="utf-8") #한글이 깨질 때는 인코딩을 직접 기입한다 (또는 cp949)
링크 정보 수집
1. GET방식과 POST방식
get과 post방식은 모두 브라우저가 서버에 요청하는 것이다. 네트워크 > Js > Headers > Request Method에서 확인할 수 있다.
- GET : 필요한 데이터를 Query String에 담아 전송한다. 쿼리 스트링은 URL의 끝에 ?와 함께 이름과 값으로 쌍을 이루는 요청 파라미터를 말한다. 만일 요청 파라미터라 여러개면 &로 연결한다.
- 예시) 네이버 웹툰 <독립일기> 3페이지 링크 중 webtoon/list?titleId=748105&weekday=thu&page=3
- 네트워크 > JS > payload 로 가면 query string parameter라고 확인 가능
- 특징) ㉮브라우저의 히스토리에 남고 ㉯길이 제한이 있다. ㉰보안 문제 때문에(url에 정보가 노출됨) 중요한 정보를 다루는 것을 지양한다고 한다.
- POST : 전송할 데이터를 HTTP 메시지 body의 Form Data에 담아 전송한다. 리소스 생성 및 변경을 위해 만들어졌다. 회원 가입할 때 적은 정보 폼, 물건이나 음식을 주문할 때 메시지를 입력하고 버튼을 누를 때 주로 사용한다.
- header에 body(요청 데이터)의 콘텐츠 타입을 명시하는 Content-Type 헤더를 포함해야 한다.
- 네트워크 > XHR > Payload로 가면 Form Data라고 확인 가능
- 특징) ㉮브라우저의 히스토리에 남지 않고 ㉯길이 제한이 없다. ㉰url에 정보가 노출되지 않아 상대적으로 보안적이다.
2. requests로 수집
response = requests.get(url) #웹페이지의 결과를 받아온다
-상세정보(링크) 수집을 위해서는 requests를 써야 한다
-인코딩 기능이 내재한다
response.status_code #응답코드를 확인할 수 있다
200 == ok. 오류 없이 정상 응답했다
BeautifulSoup으로 html 읽기 쉽게 만들기
뷰티풀숩은 읽어온 사이트의 html문서를 해석하려는 목적으로 사용한다. 데이터 수집 도구가 아니며 html을 보기 좋게 parsing해준다.
html = bs(response.text) #bs로 수집한 html문서에서 링크 정보를 찾는다
-json은 뷰티풀숩을 사용할 필요가 없다고 한다
링크 정보 찾기
1. find_all과 select
더보기
https://www.crummy.com/software/BeautifulSoup/bs4/doc.ko/ 뷰티풀숩 공식 문서 참고
find_all과 select는 모두 특정 태그를 찾는데 사용하는 함수다.
soup.find_all('a')
-전체 문서를 훑어서 결과를 찾고 모든 a태그를 찾아준다.
-메뉴, 페이징 등 모든 a태그가 있는 정보가 추출돼 전처리가 복잡해진다.
soup.find_all("a", class_="sister")
soup.find_all("a", "sister") #2번째 인자는 attrs인데 문자열을 쓰면 class처럼 탐색한다
class 지정도 가능하다
- select()
soup.select('td.data-title.aLeft > a')
-네트워크 탭에서 copy selector한 후 필요한 링크만 남겨 select함수를 적용할 수 있다.
-원래 링크에는 tr:nth-child(3)이런 코드도 있었는데 이는 순서에 관한 정보라 지워줘야 한다.
soup.select(".sister") #class로 태그를 찾는다
soup.select("#link1") #id로 태그를 찾는다
-다른 태그 바로 아래에 있는 태그를 찾을 수 있어 편리하다
-find_all보다는 select를 추천하셨다
2. 글번호 가져오기
a_list = html.select("td.data-title.aLeft > a")
a_list[1]['href'] #링크 정보 중 글번호 숫자까지 가져오기
a_list[1]['href'].split("/")[-1] #글번호 위해 '/'기준으로 문자열 슬라이싱 후 마지막 값 가져오기
#for문에 넣어 글번호 가져오기 반복
a_link_no = []
for a_tag in a_list:
a_link_no.append(a_tag['href'].split("/")[-1])
a_link_no = [a_tag['href'].split("/")[-1] for a_tag in a_list] #리스트 컴프리헨션으로 간단하게 만들어줄 수 있다
3. 컬럼 생성
table[0]["글번호"] = a_link_no #df의 마지막 컬럼으로 생성됨
데이터 프레임 합치기(1) : 전치행렬
table[[0,1]].set_index(0).T
#테이블의 [0]열과 [1]열을 가공한다
#set_index(0) [0]열을 인덱스 형태로 만들어준다
#.T == transpose() 전치행렬, 행과 열을 교환한다
table[[2,3]].set_index(2).T
#테이블의 [2]열과 [3]열을 가공한다
#set_index(2) [2]열을 인덱스 형태로 만들어준다
#.T == transpose() 전치행렬, 행과 열을 교환한다
데이터 프레임 합치기(2) : concat, merge, join
더보기
0301 실습파일 이미지 참고하기
아래의 파라미터들은 디폴트값이다.
1. concat()

pd.concat([df1,df2], axis=1)
#axis=0 (행 기준, 디폴트)상하로 이어붙이기 axis=1 (열 기준)좌우로 이어붙이기
2. merge()

pd.merge(df_left, df_right, how='inner', on=None)
#df_left 왼쪽에 위치할 df
#df_right 오른쪽에 위치할 df
#how='inner' 교집합(두 df 고유값의 교집합을 기준으로 병합)
#on=None 아무 옵션을 지정하지 않겠다(어떤 옵션이 가능한 지는 나중에 찾아보자)
-merge는 어떤 키(컬럼?)가 기준이 되는지 지정해줘야 한다
-만일 3개 이상의 dataframe을 합치고 싶으면 2개씩 merge해줘야 한다
3. join()
df1.join(df2. how='left')
#df1이 왼쪽, df2가 오른쪽에 위치하게 됨
#how='left' 행 인덱스를 기준으로 결합
기타
- 수도코드(pseudocode) 세우기 : 코드를 짜기 전 알고리즘을 설계해 보는 것. 진행 상황을 글로 써 놓으면 코드를 짜기 수월하고 타인이 이해하기가 쉽다. 목표와 방법을 공유해 협업을 원활하게 해주기도 한다.
- table.shape[0]은 데이터 프레임의 행의 갯수, table.shape[1]은 데이터 프레임의 열의 갯수
- try - except 구문 : 오류가 나더라도 실행을 지속한다.
- raise Exception(f"{page_no}페이지를 찾을 수 없습니다.") 실행은 계속하고 예외 메시지만 출력하도록 하는 방법
- soup.get_text() 뷰티플숩 함수. 텍스트만 가져온다
- type( ) 타입(str, int, float) 확인
- pd.concat( ) 데이터 병합
출처) 멋쟁이 사자처럼 AI스쿨 7기 박조은 강사님 강의자료