Seongwon Lim

[Python] HTML 코드를 이해하여 크롤링 다루기 본문

Python

[Python] HTML 코드를 이해하여 크롤링 다루기

limsw 2022. 5. 8. 16:23
반응형

이전 포스팅 글에서는 태그의 클래스명(class=”...”) 을 가지고 내용을 추출하는 방법을 알아보았다. 이번 포스팅 글에서는 임의로 작성된 HTML 코드를 이해하여 작성된 HTML Content를 가지고 파이썬으로 크롤링 하는 다양한 방법들을 살펴볼 예정이다.

먼저 데이터를 추출하기 위한 임의의 HTML 코드는 다음과 같이 작성했다.

<html>
	<body>
		<h1 id="title">임의로 작성된 HTML 코드 타이틀</h1>
		<p id="first">크롤링이란? 예시로 크롤링 이해하기</p>
		<p class="myclass">HTML 코드를 이해하여 크롤링 다루기</p>
	</body>
</html>

태그를 이용한 데이터 추출

content = """
<html>
	<body>
		<h1 id="title">임의로 작성된 HTML 코드 타이틀</h1>
		<p id="first">크롤링이란? 예시로 크롤링 이해하기</p>
		<p class="myclass">HTML 코드를 이해하여 크롤링 다루기</p>
	</body>
</html>
"""

soup = BeautifulSoup(content, 'html.parser')

data = soup.find("h1")

크롤링을 하는 방법 중 하나는 태그를 이용하여 데이터를 추출하는 것이다.

예를 들어 h1 태그를 가진 데이터를 추출하고 싶다면 위와 같이 find() 메서드 안에 파라미터로 태그를 주면 body 태그 안에 존재하는 태그들 중 h1태그를 찾아서 해당 결과를 반환한다. 결과는 다음과 같다.

태그를 제외한 뒤 내용만 추출하고 싶은 경우 2번째 출력문을 이용하면 된다.

이번에는 data = soup.find("p")로 코드를 수정한 뒤 p태그를 추출해 보았다.

HTML 코드에는 2개의 p태그가 존재하지만 반환된 결과는 1개 뿐이었다.

조건에 부합하는 데이터 모두 가져오기

위의 예시에서 2개의 p태그를 모두 가져오고 싶은 경우에는 BeautifulSoup의 메서드 중 findAll() 메서드를 사용하면 된다.

soup.findAll()로 코드를 수정하고 data 변수를 출력시켜 보았다. 위의 결과처럼 2개의 태그가 리스트에 저장된 것을 확인할 수 있다.

추가적으로 안의 내용만 추출하여 저장하고 싶은 경우에는 다음과 같이 파이썬 코드를 간단하게 구현할 수 있다.

title_list = []

for item in data:
    title_list.append(item.text)
    
print(title_list)
# 출력 결과 : ['크롤링이란? 예시로 크롤링 이해하기', 'HTML 코드를 이해하여 크롤링 다루기']

다중 조건을 이용하여 데이터 추출하기

이전에 find() 메서드를 이용하여 p태그를 추출 했을 때 결과는 최상위에 있는 p태그 1개를 값으로 반환했었다.
이번에는 다중 조건을 추가하여 사용자가 원하는 데이터를 추출하는 예제를 살펴볼 것이다.

2번째 조건으로 클래스명(classname) 이용하기

content = """
<html>
	<body>
		<h1 id="title">임의로 작성된 HTML 코드 타이틀</h1>
		<p id="first">크롤링이란? 예시로 크롤링 이해하기</p>
		<p class="myclass">HTML 코드를 이해하여 크롤링 다루기</p>
		<p class="myclass">다중 조건 예시를 위한 문장</p>
	</body>
</html>
"""

soup = BeautifulSoup(content, 'html.parser')

data = soup.findAll("p")
myclass_data = soup.findAll("p", "myclass") # 또는 2번째 인자에 class_="myclass"

예시를 들기 위해 p태그를 한 줄 추가했다. 이 때 해당 태그의 클래스명을 바로 위 태그와 동일하게 myclass로 주었다.

그 다음 data, myclass_data 변수를 출력해보았다.

myclass_data 변수의 경우 클래스명이 myclass인 태그 2개만 추출된 것을 확인할 수 있다. 이처럼 태그가 같은 태그를 추출할 때 2번째 파라미터에 조건을 추가하여 데이터를 한번 더 전처리 하여 원하는 데이터를 추출할 수 있다.

2번째 조건으로 id값 이용하기

이번에는 3개의 p태그 중에서 첫번째 태그를 findAll() 메서드를 이용해서 가져오기 위해서는 어떻게 해야할까?

data = soup.findAll("p", id="first")

이렇게 data 변수를 수정하면 된다. 2번째 파라미터에 id를 이용하여 조건을 추가 후 데이터를 추출한 것이다. HTML 문법에서 태그들의 id 값은 중복되지 않기 때문에 크롤링에서 id값을 이용하여 데이터를 추출할 때에는 1개의 데이터가 반환된다.

만약에 findAll() 메서드를 이용하지 않는다면 어떻게 구현할 수 있을까?

data = soup.find(id="first")

위와 같이 태그를 이용하여 찾는 것이 아니라 첫번째 인자에 들어오는 값을 id를 이용하여 찾는 방법도 있다.

2번째 조건으로 attribute 이용하기

이번에는 content 변수를 다음과 같이 수정했다.

<html>
	<body>
		<h1 id="title">임의로 작성된 HTML 코드 타이틀</h1>
		<p id="first">크롤링이란? 예시로 크롤링 이해하기</p>
		<p class="myclass">HTML 코드를 이해하여 크롤링 다루기</p>
		<p class="myclass" align="center">다중 조건 예시를 위한 문장</p>
	</body>
</html>

3번째 p태그에 속성으로 align="center"를 넣어주었다.
이제 다중 조건으로 p태그와 align이 center인 데이터를 추출하기 위해서는 다음과 같이 data 변수를 수정하면 된다.

data = soup.find("p", attrs={"align": "center"})

# 단일 조건으로도 사용할 수 있다.
data = soup.find(attrs={"align": "center"})

결과를 살펴보면 3번째 p태그가 알맞게 온 것을 확인할 수 있다.

번외로 attrs안에는 여러 조건이 올 수 있다.

data = soup.find(attrs={"align": "center", "class": "myclass"})

예를 들면 위 코드는 이전 예시와 같이 동일하게 3번째 p태그를 반환하지만 attrs 의 key-value 쌍을 2개로 주어 데이터를 추출할 때 조건을 더 상세화하여 추출한 것이다.

Comments