13일차 Web Crawling-2

정지원·2024년 3월 8일
0

에이블 스쿨 복습

목록 보기
16/51
post-thumbnail

어제 Kakao API에 이어 오늘은 Naver API를 사용해 본다!!

1. Naver API

(1) 검색어 트랜드 API

  • 네이버 DataLab에서 검색어 트랜드를 입력하여 통계를 볼 수 있다.

  • 조회하면 이런 지표를 볼 수 있다.

(2) requests token 얻기

  • https://developers.naver.com 여기에서 app 등록하여 key를 획득하여 데이터를 가져와야 한다.

  • 이런식으로 Client ID와 Client Secret을 가져온다.

(3) 통합검색어 트렌드 API

# 1. App Key 얻기: http://localhost 으로 URL 사용함
CLIENT_ID, CLIENT_SECRET = 'mkdP1lOXXiHZjKxRVszT', 'KxJHnMXR**'

# 2. document: url(params, headers)
url = 'https://openapi.naver.com/v1/datalab/search'
params = {
    'startDate': '2018-01-01', # 조회 기간 시작 날짜
    'endDate': '2024-03-01', # 조회 기간 종료 날짜
    'timeUnit': 'month', # 구간 단위
    'keywordGroups' : [
        {'groupName': '트위터', 'keywords': ['트위터', '트윗']},
        {'groupName': '페이스북', 'keywords': ['페이스북', '페북']},
        {'groupName': '인스타그램', 'keywords': ['인스타그램', '인스타']}
    ],    
}
header = {
    'X-Naver-Client-Id': CLIENT_ID,
    'X-Naver-Client-Secret': CLIENT_SECRET,
    'Content-Type': 'application/json'
}

# 3. request(url: params, headers) > response: json(str)
response = requests.post(url, json.dumps(params), headers=header)


# 4. json(str) > list, dict : DataFrame 생성
data = response.json()['results']

# 5. 데이터프레임으로 변경
dfs = []
for row in data:
    df = pd.DataFrame(row['data'])
    df['title'] = row['title']
    dfs.append(df)

result= pd.concat(dfs, ignore_index=True)
result.tail()

  • 이처럼 앞의 카카오 API와 유사한 방법으로 데이터를 크롤링할 수 있다.
  • 주의할 점은 메서드가 GET 방식, POST 방식인지 확인하는 것이다.
  • 파라미터를 확인하여 어떤식으로 정보를 가져올지 확인하여야 한다.
  • 네이버 API는 params에 파라미터 형식을 넣어주었다.
  • 또, header 요청을 해야한다.

2. 직방 원룸 매물 데이터 수집

(1) 동이름으로 위도 경도 구하기

  • 직방 사이트에서 원하는 동의 위도 경도 정보를 꺼내와야 한다.
  • 그러기 위해서는 URL을 불러와야 한다.
  • url을 불러올때 한글은 인식을 못해서 아래와 같이 인코딩 되어있다.
  • 주소를 가독성있게 하려면 디코딩을 하여 아래와 같은 결과를 낼 수 있다.

addr = '망원동'

url = f'https://apis.zigbang.com/v2/search?leaseYn=N&q={addr}&serviceType=원룸'
response = requests.get(url)

# response.json()['items']가 리스트로 출력되어 0번째 데이터 가져옴
data = response.json()['items'][0] 
lat, lng = data['lat'], data['lng']
lat, lng

(2) 위도 경도로 geohash 알아내기

  • oneroom에 들어가서 나오는 geohash를 구할거다.
pip install geohash2 # 라이브러리 설치

import geohash2

# precision 숫자가 클 수록 영역이 작아짐
geohash = geohash2.encode(lat, lng, precision=5)
geohash

>
'wydjx'

(3) geohash로 매물 아이디 가져오기

  • 마찬가지로 url을 디코딩해주고 가져온다.
  • request방식이 Get 방식인 것 확인
# url 저장
url = f'https://apis.zigbang.com/v2/items/oneroom\
?geohash={geohash}&depositMin=0&rentMin=0&salesTypes[0]=전세&salesTypes[1]=월세\
&domain=zigbang&checkAnyItemWithoutFilter=true'

response = requests.get(url) # Get방식으로 불러오기

items = response.json()['items'] # items변수에 items속성 저장
items = [item['itemId'] for item in items]

(4) 매물 아이디로 매물 정보 가져오기

# list에서 가져옴 url
url = 'https://apis.zigbang.com/v2/items/list'

# payload 탭에 가면 있음
params = {
    'domain' : 'zigbang',
    'item_ids' : items
}
# response = response.post(url, json.dumps(params)) # 한글이 params에 없기 때문에 안해줘도 된다
response = requests.post(url, params)

pd.options.display.max_columns = 40 # 제한을 40으로 함, row도 가능

# json 형식으로 불러오기
data = response.json()['items']

# dataframe으로 변경
df = pd.DataFrame(data)

# 컬럼 확인
data = response.json()['items']
columns = ['item_id', 'sales_title', 'deposit', 'rent', 'size_m2', 'floor', 'title','address1']
df = pd.DataFrame(data)[columns]

# 마무리
df = df[df['address1'].str.contains('망원동')].reset_index(drop=True)

3. HTML

(1) HTML 정의 및 구성 요소

1) HTML 정의

  • HTML은 Hyper Text Markup Language의 약자로 웹 문서를 작성하는 마크업 언어이다.

2) HTML 구성요소

  • Document : 한페이지를 나타내는 단위
  • Element : 하나의 레이아웃을 나타내는 단위 : 시작태그, 끝태그, 텍스트로 구성
  • Tag : 엘리먼트의 종류를 정의 : 시작태그(속성값), 끝태그
  • Attribute : 시작태그에서 태그의 특정 기능을 하는 값
    • id : 웹 페이지에서 유일한 값
    • class : 동일한 여러개의 값 사용 가능 : element를 그룹핑 할때 사용
    • attr : id와 class를 제외한 나머지 속성들s
  • Text : 시작태그와 끝태그 사이에 있는 문자열
%%html
<div id = 'contents' class='wrap'>
    <button class = 'btn no1' type = 'button' value = '1'>Btn1</button>
    <button class = 'btn no2' type = 'button' value = '2'>Btn2</button>
</div>

3) HTML 구조

  • DOCTYPE
    • 문서의 종류를 선언하는 태그
  • html
    • head
      • meta
        • 웹페이지에 대한 정보를 넣음
      • title
        • 웹페이지의 제목 정보를 넣음
    • body
      • 화면을 구성하는 엘리먼트가 온다.

4) HTML 태그

<head></head>

  • title을 나타낼때 사용
  • Head는 총 6가지 종류의 태그가 있음(h1~h6)
  • 숫자가 커질수록 문자의 크기가 줄어듦
%%html
<h1>제목</h1>
<h3>제목</h3>
<h5>제목</h5>

<p></p>

  • 한줄의 문자열을 출력하기 위한 태그
%%html
<p>한 줄의 정보를 담음</p>
<p>가장 많이 쓴다</p>

<span></span>

  • 한블럭의 문자열을 표현하기 위한 태그
%%html
<span>한 줄이 아닌 한 블럭으로 데이터 출력</span>
<span>이렇게 연결이 된다</span>

<pre></pre>

  • 줄바꿈이나 띄어쓰기가 적용되는 태그
%%html
<pre>
    이렇게
띄어서 표시가 가능함
    탭도 가능
</pre>

<code></code>

  • 코드를 작성하는 태그
  • 들여쓰기나 두칸 이상의 공백은 적용이 안된다.
%%html
<code>
코드로 나옴       신기해٩()و
</code>

5) 문제 이외의 HTML 태그

<div></div>

  • 레이아웃을 나타내는 태그
%%html
<div>
    <div>div1</div>
    <div>div2</div>
</div>
<div>div3</div>

<table></table>

  • 로우와 컬럼이 있는 테이블 모양을 나타낼때 사용하는 태그
%%html
<table>
    <caption>테이블제목</caption>
    <thead>
        <tr>
            <th>table1</th> <!-- th랑 td 같음-->
            <th>table2</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>data1</td>
            <td>data2</td>
        </tr>   
        <tr>
            <td>data3</td>
            <td>data4</td>
        </tr>
    </tbody>
</table>

<ul></ul>, <li></li>

  • 리스트를 나타내는 태그
  • 목록데이터 출력시 자주 사용
%%html
<ul>
    <li>data1</li>
    <li>data2</li>
</ul>

<a></a>

  • 링크를 나타내는 태그
  • href 속성에 url을 넣음
    • url과 상대경로를 모두 사용 가능
    • target="_blank"는 링크를 열때 새탭에서 열도록 하는 기능이 있음
%%html
<a href='https://kt.com' target='_blank'>Move KT</a>

<!--target='_blank'는 새탭을 열어서 함-->

<image></image>

%%html
<img src='https://cfm.kt.com/images/v2/layout/gnb-ktlogo.png' alt='kt logo'></img>

<!-- alt='' 글자로 이미지 말해줌 -->

<iframe></iframe>

  • 외부 url 링크 페이지를 보여주기 위한 엘리먼트
  • 모든 웹 페이지를 보여줄수있는건 아니고 iframe으로만 출력이 되던가 안되거나 하는등의 설정을 할수 있음
%%html
<iframe src='https://kt.com' width='100%' height='200px'></iframe>

<input></input>

  • 문자열을 입력받을때 사용하는 타입
# text
%%html
<input type='text' placeholder='이메일'></input>

# password
%%html
<input type='password' placeholder='비밀번호'></input>

# radio
%%html
<input type='radio' name='no1'>btn 1</input>
<input type='radio' name='no1'>btn 2</input>

<input type='radio' name='no2'>btn 3</input>
<input type='radio' name='no2'>btn 4</input>

<!-- name='no1'으로 그룹 나눔-->

# checkbox
%%html
<input type='checkbox' name='no1'>btn 1</input>
<input type='checkbox' name='no1'>btn 2</input>

# select, option
%%html
<select>
    <option>opt1</option>
    <option>opt2</option>
    <option>opt3</option>
</select>

# textarea
%%html
<textarea rows='4' cols='50'></textarea>

# button
%%html
<button class = 'btn no1' type = 'button' value = '1'>Btn1</button>
<button class = 'btn no2' type = 'button' value = '2'>Btn2</button>

4. CSS selector

(1) Element Selector

  • 엘리먼트를 이용하여 선택할때 사용
  • css selector로 div를 사용하면 가장 위에 있는 dss1이 선택
%%html
<div>dss1</div>
<p>dss2</p>
<span>dss3</span>

# dom.select_one('div') => dss1

(2) ID Selector

  • 아이디를 이용하여 선택할때 사용
  • 아이디를 셀렉할때는 #(아이디 이름)으로 선택
  • css selector로 #ds2를 사용하면 dss2가 선택
  • 여러개를 셀렉할때는 ,로 구분
  • css selector로 #ds2, #ds3를 사용하면 dss2와 dss3가 선택
<p id="ds1">dss1</p>
<p id="ds2">dss2</p>
<p id="ds3">dss3</p>

# dom.select_one('#ds1') => dss1
# dom.select('p') => [dss1, dss2, dss3] 모두 선택

(3) Class Selector

  • 클래스를 이용하여 선택할때 사용
  • 클래스를 셀렉할때는 .(클래스 이름)으로 선택
  • 엘리멘트를 그룹핑하여 스타일을 적용할때 사용
  • css selector로 .ds2를 사용하면 dss2, dss3가 선택
<p class="ds1">dss1</p>
<p class="ds2">dss2</p>
<p class="ds2">dss3</p>
<p class="ds5">dss5</p>
<span class="ds5">dss6</span>

# .ds2 		=> 		dss2
# .ds1,.ds3 => 		dss1
# p.ds5 	=> 		dss5
# span.ds5 	=> 		dss6

(4) not Selector

  • 셀렉터로 엘리먼트를 하나만 제거하고 싶을때 사용
  • not을 사용하여 셀렉트 할때에는 :not(선택에서 제거하고 싶은 셀렉터)으로 선택
  • 아래의 HTML에서 .ds:not(.ds2)으로 셀렉트 하면 class가 ds2인 클래스를 제외 하고 나머지 ds1, ds3, ds4, ds5가 선택
<p class="ds ds1">ds1</p>
<p class="ds ds2">ds2</p>
<p class="ds ds3">ds3</p>
<p class="ds ds4">ds4</p>
<p class="ds ds5">ds5</p>

# 둘다 같은 결과값 나옴
# .ds1, .ds3, .ds4, .ds5		=> ds2제외
# .ds:not(.ds2)   	 			=>	.ds 클래스 중 ds2제외

(5) first-child Selector

  • 엘리먼트로 감싸져있는 가장 처음 엘리먼트가 설정한 셀렉터와 일치하면 선택
  • .ds:first-child로 설정하면 ds1과 ds3가 선택
<body>
    <p class="ds" id="ds1">ds1</p>
    <p class="sc" id="ds2">ds2</p>

    <div class="ds">
        <p class="ds ds1">ds3</p>
        <p class="ds ds2">ds4</p>
        <p class="ds ds3">ds5</p>
        <p class="ds ds4">ds6</p>
        <p class="ds ds5">ds7</p>
    </div>
</body>
  • div.ds 엘리먼트의 가장 처음 .ds를 선택하고 싶으면 div.ds > .ds:first-child로 셀렉터를 작성

(6) last-child Selector

  • 엘리먼트로 감싸져있는 가장 마지막 엘리먼트가 설정한 셀렉터와 일치하면 선택
  • .ds:last-childdiv.ds가 선택되어 ds3~ds7이 선택
<body>
    <p class="ds" id="ds1">ds1</p>
    <p class="sc" id="ds2">ds2</p>

    <div class="ds">
        <p class="ds ds1">ds3</p>
        <p class="ds ds2">ds4</p>
        <p class="ds ds3">ds5</p>
        <p class="ds ds4">ds6</p>
        <p class="ds ds5">ds7</p>
    </div>
</body>

(7) nth-child Selector

  • 엘리먼트로 감싸져있는 n번째 엘리먼트가 설정한 셀렉터와 일치하면 선택
  • .ds:nth-child(3), .ds:nth-child(4)로 설정하면 ds4, ds5가 선택
  • nth-child의 ()안의 숫자는 가장 첫번째가 0이 아니라 1로 시작
<div class="wrap">
    <span class="ds">ds2</span>
    <p class="ds ds1">ds3</p>
    <p class="ds ds2">ds4</p>
    <p class="ds ds3">ds5</p>
    <p class="ds ds4">ds6</p>
    <p class="ds ds5">ds7</p>
</div>

(8) 모든 하위 depth(공백) Selector

  • 공백문자로 하위 엘리먼트를 셀렉트 했을때, 모든 하위 엘리먼트를 선택
  • .contants h1를 선택하면 inner_1, inner_2가 선택
<div class="contants">
    <h1>inner_1</h1>
    <div class="txt">
        <h1>inner_2</h1>
    </div>
</div>

(9) 바로 아래 depth(>) Selector

  • >문자로 하위 엘리먼트를 셀렉트 했을때, 바로 아래 엘리먼트를 선택
  • .contants > h1를 선택하면 inner_1이 선택
<div class="contants">
    <h1>inner_1</h1>
    <div class="txt">
        <h1>inner_2</h1>
    </div>
</div>

총 정리

  • 하나의 엘리먼트 선택
    Tag : div
    id : #data
    class : .data
    attr : [value='no1']

.data:not(.data1) : data 클래스 모두에서 data1 클래스 엘리먼트 제외
.data:nth-child(3) : 3번째 하위 엘리먼트에서 .data 클래스를 가진 엘리먼트 선택

공백 : #data .btn : data 아이디 하위의 모든 btn 클래스 엘리먼트를 선택
> : #data .btn : data 아이디 한단계 하위의 btn 클래스 엘리먼트를 선택

.d1, .d2 : d1, d2 클래스 둘다 선택

회고

드디어 금요일이다~~ㅋㅋㅋㅋㅋ 예비군이슈로 수요일에 빠졌는데도 지치는 늙은이다 ˃̣̣̣̣̣̣︿˂

오늘도 어제에 이어서 웹크롤링을 배우는데 진짜 머리가 터질 뻔했다.

무머 어디서 가져고오 뭐하고 뭐하고 하는게 만만치 않다.

그래도 내가 따로 해봤던 내용들(자바스크립트, html)이 나와서 조금은 수월하게 진행했다.

근데 문제는 내가 안다고 자만하는거,,,,, 아마 처음으로 아는게 나와서 그런듯하다ㅋㅋㅋㅋㅋㅋㅋ 더 집중해서 듣자 지원아 ㅋ

주말동안 기자단 활동 준비좀하고 미니프로젝트 복습좀 해봐야겠다. 화이팅~💪😊

아 맞다 오늘 쉬프트 엔터만 누르다가 수업 중에 고정키 떠서 키보드가 안되는 상황이 와서 옴청난 당황을 탔다ㅋㅋㅋㅋㅋㅋㅋㅋ

셀테도 다행히 객관식이라 다하고 체크아웃도 다 완료...ㅎ

다들 고정키 조심하시길~~

profile
뒤늦게 프로그래밍을 시작한 응애

0개의 댓글