본문 바로가기
개발/Python

python requests로 웹 페이지 크롤링 하기

by ny0011 2020. 12. 11.
반응형

웹 페이지의 html 문서를 가져오는 건 쉽다

python 라이브러리인 requests를 사용하면 f12를 누르면 나오는 elements 탭의 내용을 긁어올 수 있다

requests 공식 docs

 

Requests: HTTP for Humans™ — Requests 2.25.0 documentation

Requests: HTTP for Humans™ Release v2.25.0. (Installation) Requests is an elegant and simple HTTP library for Python, built for human beings. Behold, the power of Requests: >>> r = requests.get('https://api.github.com/user', auth=('user', 'pass')) >>> r.

requests.readthedocs.io

예를 들어서 tistory가 서비스하는 kakao의 검색 엔진(?)인 daum.net의 웹 페이지를 가져오려면 다음과 같다.

r.text에 웹 페이지가 있고 str type으로 저장된다.

import requests

def read_webpage(link):
    print('read webpage')
    r = requests.get(link)
    print(f'status code : {r.status_code}')
    if r.status_code == requests.codes.ok:
      return r.text
    else:
      r.raise_for_status()

html_text = read_webpage('https://www.daum.net/')

 

하지만 원하는 데이터를 가져오는 방법은 여러가지다.

1. python str의 find를 사용해서 index를 알아내서 원하는 데이터 위치를 출력하거나

2. bs4의 beautifulsoup을 사용해 HTML tag, class 속성 기준으로 원하는 데이터를 찾을 수 있다.

 

원하는 데이터를 실시간 검색어라고 해보자

다음의 경우 검색창 밑에 실시간 검색어가 뜬다

<a href="https://search.daum.net/search?w=tot&amp;q=%EC%97%8" class="link_favorsch @7">엄정화 컴백확정</a>

a tag로 링크 연결이 되어있고 class로는 link_favorsch와 @7, 텍스트 내용은 '엄정화 컴백확정' 이다.

link_favorsch를 찾아보면 실시간 검색어 태그는 다 이거로 되어있다

 

1. str.find() 사용

여기서 텍스트 내용인 '엄정화 컴백확정'을 가져오기 위해서

1) class="link_favorsch @인 부분의 위치를 찾고(index 변수)

2) index부터 시작해서 >의 위치를 찾아 텍스트 내용 시작 위치를 찾고(start 변수)

3) start부터 시작해서 </a>의 위치를 찾아 텍스트 내용 끝 위치를 찾는다(end 변수)

 

이걸 코드로 나타내면 다음과 같다

str.find()로 문자열을 못찾으면 -1을 반환하기 때문에 while문 종료를 이걸로 설정한다.

def find_something(text, sth):
    print(f'find {sth}')
    start = 0
    while text.find(sth, start) != -1:
      index = text.find(sth, start) # 1)
      start = text.find(">", index) # 2)
      end = text.find('</a>', start) # 3)
      print(text[start+1:end])
      
find_something('class="link_favorsch @', html_text)

 

2. bs4의 BeautifulSoup 사용

beautifulsoup 공식 docs

 

Beautiful Soup Documentation — Beautiful Soup 4.9.0 documentation

Non-pretty printing If you just want a string, with no fancy formatting, you can call str() on a BeautifulSoup object (unicode() in Python 2), or on a Tag within it: str(soup) # ' I linked to example.com ' str(soup.a) # ' I linked to example.com ' The str(

www.crummy.com

BeautifulSoup도 find()처럼 str을 읽고 그걸 html.parser를 돌려서 태그를 나누기 때문에 

requests의 결과(html_text)를 그대로 사용한다.

BeautifulSoup의 select()를 사용해서 tag 이름과 class 속성을 알면 텍스트 내용은 .text로 쉽게 알 수 있다

어떻게 보면 str.find()를 사용하는 것보다 쉽고 눈에 잘 들어오는 것 같다

 

** search_something 함수를 수정했다.

tag 하나에 classname이 여러 개 있을 때 classname 여러 개 모두에 부합하는 텍스트를 찾도록 수정해보았다.

python * 연산자를 사용해서 '가변 인자'라는 걸 사용할 수 있는데 꽤 유용해보였다

def search_something(text, tagname, *classname):
  print(f'search with bs4 : {classname}')
  soup = BeautifulSoup(text, 'html.parser')
  classname_str = '.'.join(classname)
  print(f'{tagname}.{classname_str}')
  return [tag.text.replace('\n\n\n','\n') for tag in soup.select(f'{tagname}.{classname_str}')]
    
list_favorsch = search_something(html_text, 'ul','list_favorsch')

 

 

코드는 아래 URL에 공개해두었다

github.com/ny0011/ai_mini_project

 

ny0011/ai_mini_project

python, web crawl과 친해지기. Contribute to ny0011/ai_mini_project development by creating an account on GitHub.

github.com

 

'개발 > Python' 카테고리의 다른 글

[codility] MaxCounters  (0) 2021.02.17
selenium으로 웹 정보를 스크랩해보자  (0) 2020.08.31

댓글