본문 바로가기
코딩 연습/코딩배우기

[python] 파이썬 웹 크롤링(Web Crawling) 알아보기 #2

by good4me 2020. 10. 16.

goodthings4me.tistory.com

 

■ 파이썬 웹 크롤링 실습 - 대표적인 크롤링 예시 3가지

  • HTML 크롤링
  • Ajax 렌더링 크롤링
  • JavaScript 렌더링 크롤링

 

▷ 단순 HTML 크롤링

import requests
from bs4 import BeautifulSoup

url_level1 = 'https://askdjango.github.io/lv1/'

html = requests.get(url_level1).text
soup = BeautifulSoup(html, 'html.parser')

for a_tag in soup.select('#s1_course_list .course > a'):
  print(a_tag.text, a_tag['href']) 

※ BeautifulSoup의 tag는 사전과 유사한 인터페이스를 지원하기 때문에  Key값으로 'href'를 접근하면 <a> 태그 링크를 추출할 수 있음

[실행 결과]

 

 

▷ Ajax 렌더링 크롤링

  • Ajax를 통해 데이터를 받아와서, 자바스크립트로 컨텐츠가 추가되는 사이트
  • 페이지 소스보기에서 크롤링할 본문 내용이 안보일 때 (단순 HTML 크롤링이 아닐 때)
개발자 도구(F12) Network 탭에서 F5(새로고침) 후 Name 요소의 data.json 클릭 시, 
Headers 탭에서 Request URL: https://askdjango.github.io/lv2/data.json 이 확인되고, 
Response 탭 내역에서 크릴링할 내용이 보인다.

데이터의 형태가 완전하고 값을 가져올 수 있다면, 별로도 파싱할 필요없음
(BeautifulSoup 필요없고 requests로 크롤링함)

data.json 마우스 우클릭 후 새탭(Open in new tap)으로 열기 후 리소스 url을 확인함.

good4me.co.kr

import requests
import json

url_level2 = 'https://askdjango.github.io/lv2/data.json'
html_json = requests.get(url_level2).text
course_list = json.loads(html_json)['s1']
# json.loads로 list와 dict로 변환 후, Key 's1'에 대해 추출

print(course_list.__class__)
# <class 'list'>

print(course_list)

for course in course_list:
    print(course['name'], course['url'])

 

[실행 결과]

 

 

 

▷ Ajax 렌더링 크롤링자바스크립트 렌더링 크롤링

  • 자바스크립트 객체를 통해 컨텐츠가 추가되는 사이트
  • 페이지 소스보기에서 보면, <script> 태그 내에 추출할 내용이 있음 
    (Network 탭에서 All로 F5 검색 후 찾아봐도 찾는 데이터가 없음)
  • requests 나 Beautiful에서는 <script> 내용이 단순 문자열일 뿐임 
    (정규표현식 사용하여 해당 문자열을 찾아 내용을 가져와야 함)
import requests
import re
import json

url_level3 = 'https://askdjango.github.io/lv3/'
html = requests.get(url_level3).text
#print(html)

result = re.search(r'var s1_courses = (.+);', html)
print(result)  # None 출력
re.S 옵션(re.DOTALL) 필요 (개행 포함 여부를 설정하는 옵션)
Make the '.' special character match any character at all, including a newline; 
without this flag, '.' will match anything except a newline.
import requests
import re
import json

url_level3 = 'https://askdjango.github.io/lv3/'
html = requests.get(url_level3).text

result = re.search(r'var s1_courses = (.+);', html, re.S)
print(result)
# <re.Match object; span=(1451, 5558), match='var s1_courses = [\n {"name": "개발환경 
구축하기",>

print(result.group(1))  

 

[실행 결과]

 

※ 정규 표현식 패턴을 만족하는 가장 큰 범위(세미 콜론(;))까지 확장하기 때문에 원하는 크롤링 내역을 벗어남(최소 매칭을 위해 ? 추가)

import requests
import re
import json

url_level3 = 'https://askdjango.github.io/lv3/'
html = requests.get(url_level3).text

matched = re.search(r'var s1_courses = (.+?);', html, re.S)
json_str = matched.group(1)
print(json_str)


course_s1 = json.loads(json_str)
for course in course_s1:
    #print(course['name'], course['url'])
    print('{name} {url}'.format(**course))

 

[실행 결과]

 

 

[참고] askcompany.kr - 크롤링 차근차근 시작하기

 

댓글