Ruby로 HTML을 파싱해야 하는 상황인가요?
적절한 도구가 없다면 이 작업은 생각보다 까다로울 수 있습니다.
하지만 걱정하지 마세요. Ruby에는 Nokogiri라는 훌륭한 라이브러리가 있어서 HTML 파싱이 산책처럼 쉬워집니다.
지금부터 실제 예제를 통해 하나씩 살펴보겠습니다.
Nokogiri 설치하기
먼저 다음 명령어로 nokogiri 젬(gem)을 설치합니다.
gem install nokogiri
설치 중 오류가 발생한다면 시스템 라이브러리를 사용하도록 옵션을 추가해 보세요.
gem install nokogiri -- --use-system-libraries
페이지 제목(title) 추출하기
이제 nokogiri로 파싱할 기본적인 HTML 코드 조각을 포함한 스크립트를 작성해 보겠습니다.
아래 코드를 실행하면 페이지의 제목을 가져올 수 있습니다.
require 'nokogiri' html = "<title>test</title><body>actual content here...</body>" parsed_data = Nokogiri::HTML.parse(html) puts parsed_data.title #=> "test"
HTML 문자열 대신 URL에서 직접 데이터를 파싱하고 싶다면 어떻게 해야 할까요?
이렇게 하면 됩니다.
require 'open-uri'
Nokogiri::HTML.parse(open('https://example.com')).title
이 코드는 해당 URL의 HTML을 다운로드한 뒤 페이지 제목을 반환합니다.
자, 여기서 잠깐!
제목을 가져오는 것도 유용하지만, 아마 더 실용적인 고급 예제가 궁금하실 겁니다.
그럼 웹사이트에서 링크를 추출하는 방법을 알아보겠습니다.
앵커 링크(a 태그) 추출하기
페이지의 모든 링크를 가져오려면 먼저 HTML이 필요합니다.
앞서 사용한 open-uri 기법으로 공개된 웹사이트라면 어디든 HTML을 내려받을 수 있습니다.
그런 다음 Nokogiri로 파싱하여 문서 객체(document object)를 만듭니다.
예시는 다음과 같습니다.
document = Nokogiri::HTML.parse(open('https://example.com'))
document.class
#=> Nokogiri::HTML::Document
이 객체에서 정보를 조회하는 방법은 두 가지입니다.
- XPath 쿼리 사용
- CSS 선택자 사용
먼저 XPath를 사용하는 방법부터 살펴보겠습니다.
코드는 다음과 같습니다.
tags = document.xpath("//a")
이 코드는 무엇을 하는 걸까요?
페이지의 모든 HTML 태그를 필터링하여 요청한 태그만 골라냅니다. 이 경우에는 "a" 태그, 즉 HTML에서 링크를 담고 있는 태그들이죠.
결과적으로 해당 태그들을 나타내는 Nokogiri::XML::Element 객체 배열을 얻게 됩니다.
링크의 URL과 텍스트를 함께 출력하려면 다음과 같이 작성합니다.
tags.each do |tag|
puts "#{tag[:href]}\t#{tag.text}"
end
이 코드는 모든 링크를 한 줄에 하나씩 화면에 출력합니다.
링크가 아니라 이미지 목록 같은 다른 정보를 스크래핑하고 싶다면 동일한 과정을 그대로 따르면 됩니다. 바꿔야 할 것은 원하는 태그 종류뿐입니다.
예를 들면 다음과 같습니다.
tags = document.xpath("//img")
images_urls = tags.map { |t| t[:src] }
여기서 img는 이미지를 나타내는 HTML 태그이고, src는 이미지 URL이 저장되어 있는 속성(attribute)입니다.
올바른 CSS 선택자와 속성을 찾으려면 브라우저의 개발자 도구(Developer Tools)를 활용하세요.
Nokogiri에서 CSS 선택자 사용하기
xpath 메서드 대신 css 메서드를 사용하면 CSS 선택자로 요소를 조회할 수 있습니다.
예제를 살펴볼까요?
headers = document.css("h1")
paragraphs = document.css("p")
참고:
at_css와css의 차이점은,at_css는 일치하는 첫 번째 요소만 반환하는 반면css는 일치하는 모든 요소를 반환한다는 점입니다.
CSS를 사용해도 결과는 동일합니다. 핵심은 Nokogiri에게 어떤 HTML 요소를 다룰지 알려주는 것이니까요.
대부분의 개발자가 XPath보다 CSS에 더 익숙하기 때문에, 특별한 이유가 없다면 CSS 선택자를 사용하는 편이 좋습니다.
마무리
Nokogiri 공식 문서는 아래 링크에서 확인할 수 있습니다.
https://www.rubydoc.info/github/sparklemotion/nokogiri
함께 읽으면 좋은 글:
Ruby 문자열 포매팅(String Format) 완전 정리