1. 크롤링 Tips
1) 크롬 브라우저 활용하기 : Dev Mode(ctrl + shift + i / F12)
- 원하는 요소 클릭 → 우클릭 → outerHTML 복사; 해당 요소와 관련된 태그만 추출
import requests
from bs4 import BeautifulSoup
response = requests.get("http://www.naver.com")
soup = BeautifulSoup(response.content, "html.parser")
data_list = soup.find_all("span", "service_name")
for data in data_list:
print(data.string)
2) 추출한 것에서 또 추출하기
- 더 크게 감싸는 태그를 find() 로 추출; 미리 범위 지정
- 추출된 데이터에서 find()/find_all() 로 원하는 부분 추출
import requests
from bs4 import BeautifulSoup
response = requests.get("https://davelee-fun.github.io/blog/crawl_test")
soup = BeautifulSoup(response.content, "html.parser")
# li 태그보다 상위 태그(ul) 추출; 미리 범위 지정
section = soup.find("ul", id="hobby_course_list")
# 진짜 추출하려는 태그(li)를 다시 추출
titles = section.find_all("li", "course")
for title in titles:
print(title.get_text())
3) 파이썬 문자열 함수와 함께 쓰기
- 데이터 전처리 : 추출한 데이터에서 필요 없는 부분 삭제
- strip() : 특정 문자를 기준으로 문자열을 분할
- split() : 문자열의 앞 뒤로 공백 삭제. 인자에 특정 문자를 지정할 경우, 문자열 앞 뒤에서 해당 문자를 삭제)
import requests
from bs4 import BeautifulSoup
response = requests.get("https://davelee-fun.github.io/blog/crawl_test")
soup = BeautifulSoup(response.content, "html.parser")
# li 보다 상위 태그 ul 먼저 추출; 미리 범위 지정
section = soup.find("ul", id="dev_course_list")
titles = section.find_all("li", "course")
# enumerate() : 반복 가능한 객체를 인자로 받아 해당 객체의 요소를 순회하면서, 각 요소의 인덱스와 값을 순서쌍으로 반환
# 즉, 0 (초급) - 강사가 실제 사용하는 자동 프로그램 소개 [2], ... 이런식으로 반환
for index, title in enumerate(titles): # for 인덱스번호, 인덱스 번호에 해당하는 데이터
# split("-") : - 를 기준으로 문자열 나눔 -> 리스트 형태로 반환 -> 인덱싱[-1]을 통해 우측 요소 선택
# split("[") : [ 를 기준으로 문자열 나눔 -> 리스트 형태로 반환 -> 인덱싱[0]을 통해 좌측 요소 선택
print(str(index + 1) + ".", title.get_text().split("-")[-1].split("[")[0].strip())
* cf : 문자열로만 이루어졌을 때 덧셈(+)으로 문자열 연결 가능. 다른 자료형이 섞여있는 경우 쉼표(,)로 연결
2. 다양한 크롤링 추출 방법 : CSS Selector 사용하기
- CSS Selector : find()와 같이, 웹페이지 내 타겟 데이터 선택
1) 크롬 브라우저 활용하기 : Dev Mode(ctrl + shift + i / F12)
- 원하는 요소 클릭 → 우클릭 → selector 복사; css selector 버전으로 코드 복사
2) CSS Selector 사용법
- select() 인자 자리에 태그 or CSS class명 등 넣기 → 결과값 : 리스트로 반환
- select_one() : 매칭되는 첫 번째 데이터만 반환
데이터 추출 메서드 |
반환 형태 | 반환 내용 | 사용 방법 |
find() | 태그 | 매칭되는 첫 번째 데이터만 반환 |
① 태그명 soup.find("태그명") ② 태그명/속성&속성값 soup.find("태그명", 속성="속성값") ex : class_="class명" ③ 태그명/속성값 soup.find("태그명", "속성값") ④ 태그명/속성&속성값 딕셔너리 soup.find("태그명", attrs={"속성1": "속성값1", "속성2": "속성값2", ...}) ⑤ 속성&속성값 soup.find("속성"="속성값") |
find_all() | 리스트 | 전체 데이터 반환 | find()와 동일 |
select() | 리스트 | 전체 데이터 반환 | ① 태그명 soup.select("태그명") ② 하위/자식 태그 soup.select("태그명1 태그명2 태그명3) soup.select("태그명1 > 태그명2") ③ CSS class/id명 soup.select(".class명") soup.select("#id명") ④ CSS class 명 여러개 soup.select("태그명.class명1.class명2") ⑤ 추출한 것에서 추출 items = soup.select("태그명") for item in items: dataset = item.select("태그명") for data in dataset: data.string() |
select_one() | 태그 | 매칭되는 첫 번째 데이터만 반환 |
select()와 동일 |
3) 예제
① 태그명으로 선택
# [예제1. 태그 이름으로 선택]
import requests
from bs4 import BeautifulSoup
res = requests.get("https://davelee-fun.github.io/blog/crawl_test_css.html")
soup = BeautifulSoup(res.content, "html.parser")
items = soup.select("li") # 태그 이름 'li'; 리스트로 반환
# print(items)
for item in items:
print(item.get_text())
② 하위 태그 선택
# [예제2-1. 하위 태그 선택]
import requests
from bs4 import BeautifulSoup
res = requests.get("https://davelee-fun.github.io/blog/crawl_test_css.html")
soup = BeautifulSoup(res.content, "html.parser")
# select("html body h1") : html 태그 안에, body 태그 안에, h1 태그를 선택. 직계가 아니어도 상하 관계만 정확히 써주면 됨
# select("ul > li") : ul 태그의 '자식요소'인 li태그 만 선택
# select() : 찾은 요소가 한개뿐이어도 리스트로 반환
items = soup.select("html body h1")
for item in items:
print(item.get_text())
③ 자식 태그 선택
# [예제2-2. 자식 태그 선택]
import requests
from bs4 import BeautifulSoup
res = requests.get("https://davelee-fun.github.io/blog/crawl_test_css.html")
soup = BeautifulSoup(res.content, "html.parser")
# '>' 는 바로 아래 태그인 경우를 검색
items = soup.select("ul > li")
for item in items:
print(item.get_text())
④ CSS class명으로 선택
# [예제 2-3. css class 이름으로 선택]
import requests
from bs4 import BeautifulSoup
res = requests.get("https://davelee-fun.github.io/blog/crawl_test_css.html")
soup = BeautifulSoup(res.content, "html.parser")
# '.클래스 이름' 으로 검색
items = soup.select(".course")
for item in items:
print(item.get_text())
⑤ CSS id명으로 선택
# [예제 2-4. id 이름으로 선택]
import requests
from bs4 import BeautifulSoup
res = requests.get("https://davelee-fun.github.io/blog/crawl_test_css.html")
soup = BeautifulSoup(res.content, "html.parser")
# '#id 이름' 으로 검색 가능
items = soup.select("#start")
for item in items:
print(item.get_text())
⑥ 하나의 태그에 class명이 여러개인 경우
# [예제 2-5. 하나의 태그에 클래스 이름이 여러개인 경우]
import requests
from bs4 import BeautifulSoup
res = requests.get("https://davelee-fun.github.io/blog/crawl_test_css.html")
soup = BeautifulSoup(res.content, "html.parser")
# '태그.클래스이름1.클래스이름2. ...' 으로 검색; 태그이름은 생략가능
items = soup.select("li.course.paid")
for item in items:
print(item.get_text())
⑦ select_one() 사용하여 선택
# [예제 2-7. select_one() 사용]
from bs4 import BeautifulSoup
import requests
res = requests.get("https://davelee-fun.github.io/blog/crawl_test_css.html")
soup = BeautifulSoup(res.content, "html.parser")
# ul 태그의 id가 'dev_course_list', 그 자식 태그 li의 class 이름이 'course', 'paid' 두 개를 가지는 요소를 검색
# select_one() 은 리스트가 아닌, 태그(1개)를 반환
item = soup.select_one("ul#dev_course_list > li.course.paid")
print(item.get_text()) # 태그는 빼고 문자열만 추출
⑧ 추출한 것에서 추출하기
# [예재 2-8. 추출한 것에서 추출하기]
# find()/select() 로 가져온 객체에는 find()/select() 함수를 교차 사용 가능 ← find_all() 도 사용 가능
from bs4 import BeautifulSoup
import requests
res = requests.get("https://davelee-fun.github.io/blog/crawl_html_css.html")
soup = BeautifulSoup(res.content, "html.parser")
# 목적 : 상위/하위 태그를 구분하여 반환
items = soup.select("tr") # 1. 행 리스트를 먼저 추출
for item in items:
columns = item.select("td") # 2. 행 리스트의 각 행 요소에 속한 열을 추출
row_str = ""
for column in columns:
# row_str 에 "," + column.get_text() 를 추가해서 다시 row_str에 저장
row_str += "," + column.get_text()
print(row_str[1:]) # 문자열's 인덱스1 부터 끝까지 출력
'Python > 08. 크롤링과 웹 기본' 카테고리의 다른 글
01. 크롤링 코드 패턴 (0) | 2024.07.27 |
---|