HTML & CSS

[45-2 BeautifulSoup] 특정 요소 찾고 선택하기, 웹사이트 스크래핑하기, find, find_all, select_one, select, getText(), get()

Olivia-BlackCherry 2022. 10. 23. 13:20
from bs4 import BeautifulSoup

with open("index.html", encoding="UTF-8") as file:
    contents = file.read()

soup = BeautifulSoup(contents, "html.parser")
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title>올리비아의 개인 사이트</title>
  <link rel="stylesheet" href="styles.css">
</head>

<body>
  <img src="my_love_anne.png" alt="코딩스쿨 파이썬 독학 코딩 공부">
  <h1>Olivia, Kim</h1>
  <p><em><strong>파이썬 문법, 메타버스, 머신러닝, 인공지능</strong>을 즐겁게 배우고, 열정있게 가르칩니다.</em></p>
  <br>
  <hr size="1" color="black">
  <h3>강의 내용</h3>
  <p>
  <ol type="1" reversed>
    <li id="lesson1">파이썬 기초 문법 수업</li>
    <li class ="lesson"> 파이썬 문법 활용한 단순한 프로그래밍 구현 수업</li>
    <li class ="lesson">파이썬, 판다스 활용한 데이터 분석 수업</li>
    <li>API 활용 데이터 활용 수업</li>
    <li>메타버스 세계 구축 수업</li>
    <li>메타버스 공간 제작</li>
  </ol>
  </p>

  <h3>대상</h3>
  <a href="who.html">학습 대상</a>

  <h3> 블로그</h3>
  <p>
    <em><strong><a href="https://olivia-blackcherry.tistory.com/category/%ED%8C%8C%EC%9D%B4%EC%8D%AC/%ED%8C%8C%EC%9D%B4%EC%8D%AC%28python%29%20%EC%B4%88%EA%B8%89?page=13">올리비아코딩스쿨 블로그</a></strong></em>
  </p>

  <h3><a href="contact.html">연락처</a></h3>
</body>

</html>

 

 

find_all()

문서에서 특정 태그 전부를 찾을 수 있으며 리스트 형태로 출력된다.

soup.find_all(name="a")

>>[

<a href="who.html">학습 대상</a>, 

<a href="https://olivia-blackcherry.tistory.com>올리비아코딩스쿨 블로그</a>, 

<a href="contact.html">연락처</a>

]

 

all = soup.find_all("li")
print(all)

>>[

<li id="lesson1">파이썬 기초 문법 수업</li>, 

<li>파이썬 문법 활용한 단순한 프로그래밍 구현 수업</li>, 

<li>파이썬, 판다스 활용한 데이터 분석 수업</li>, 

<li>API 활용 데이터 활용 수업</li>, 

<li>메타버스 세계 구축 수업</li>, 

<li>메타버스 공간 제작</li>

]

 

 

find(name=?, id=?)

특정 태그에서 특정 id만 출력하고 싶을 때 사용한다.

naem과 id 모두 매치되야 한다. 

li= soup.find(name="li", id="lesson1")
print(li)

>><li id="lesson1">파이썬 기초 문법 수업</li>

 

 

find(name=?, class_=?)

특정 태그에서 특정 class만 출력하고 싶을 때 사용한다. 

class를 쓸 때는 class+ '_' 언더바를 추가한다.

name과 class 모두 매치되야 한다.

class_lesson = soup.find(name="li", class_="lesson")
print(class_lesson)

>><li class="lesson"> 파이썬 문법 활용한 단순한 프로그래밍 구현 수업</li>

 

 

select(selector=?)

특정 요소를 선택자를 이용해서 뽑아내기(드릴 다운),

해당되는 전부를 리스트 형태로 가져옴 

?에는 문자열 형태로 온다.

 

- HTML 선택기

drill_down = soup.select_one("p em strong")
print(drill_down)

>><strong>파이썬 문법, 메타버스, 머신러닝, 인공지능</strong>

 

- ID 선택기( # 사용하기)

id_selector = soup.select(selector="#lesson1")
print(id_selector)

>><li id="lesson1">파이썬 기초 문법 수업</li>

 

- CSS 선택기

CSS에서 selector을 이용하는 것처럼 사용한다.

class_lesson=soup.select(selector=".lesson")
print(class_lesson)

class 안의 모든 요소를 가지고 옴, CSS코드를 적을 때와 마찬가지로 점을 찍어야 한다.---> .class

키워드 selector는 적어도 되고, 지워도 된다.

class_lesson=soup.select(".lesson")
print(class_lesson)

>>[

<li id="lesson1">파이썬 기초 문법 수업</li>]
[<li class="lesson"> 파이썬 문법 활용한 단순한 프로그래밍 구현 수업</li>

]

 

 

select_one()

특정 요소를 하나만 드릴 다운하기

 

getText()

위에서 출력된 태그에서, 글자들만 세부적으로 가져오고 싶다면 getText() 메소드를 이용한다. 

anchors = soup.find_all(name="a")
for anchor in anchors:
    print(anchor.getText())

>>학습 대상
올리비아코딩스쿨 블로그
연락처

 

get()

특정 속성값을 가져오고 싶을 때 사용한다.

하이퍼링크의 URL만 가져오고 싶을 때 아래와 같이 쓴다.

for anchor in anchors:
    print(anchor.get("href"))

>>who.html
https://olivia-blackcherry.tistory.com
contact.html

 

 

<예제>

실제 인터넷에 있는 웹사이트에서 스크래핑을 해보자

https://news.ycombinator.com/

예제로 위의 사이트에 있는 뉴스 기사 목록을 스크래핑 해볼 것이다.

 

 

1. 웹페이지에 있는 텍스트 전부 불러오기

import requests
response=requests.get(url="https://news.ycombinator.com/")
print(response.text)

 

2. 웹페이지에서 HTML 코드 살펴보기

오른쪽 마우스 버튼 클릭> 검사> 코드를 살펴보자

 '1. GitHub Copilot Investigation'는 <a>태그 안의 요소이며 클릭하면 href의 URL로 연결된다. 

 

'810 points'는 span 태그 안에 위치해 있으며, class는 score이며 id도 있다.

 

f= soup.find(name="span", class_="score")
print(f.getText())

e=soup.find("span", "score")
print(e.getText())

g=soup.select_one("span .score")
print(g.getText())

>>1100 points
1100 points
1100 points

 

3. 웹페이지에서 스크래핑하기

#title 가져오기
article_titles =[]
titles= soup.find_all(name="span", class_="titleline")
for title in titles:
    article_titles.append(title.find("a").getText())
print(article_titles)

#link 가져오기
article_links =[]
for title in titles:
   article_links.append(title.select("span a")[0].get("href"))
print(article_links)

#point 가져오기
article_points =[]
points = soup.find_all(name="span", class_="score")
for point in points:
    all = point.getText()
    article_points.append(int(all.split(' ')[0]))
print(article_points)

>>['GitHub Copi\xadlot inves\xadti\xadga\xadtion', 'The FreeBSD/Firecracker Platform', 'TOTP tokens on my wrist with the smartest dumb watch', 'How to become a pirate archivist', 'Almost 25% of world’s seafloor now mapped', 'AI Data Laundering', 'North Paw', 'Our moon has been slowly drifting away from Earth over the past 2.5B yrs', 'Real-World Engineering Challenges: Migrations', '"The Social Network" synth sounds', 'Gödel’s first incompleteness theorem – an interactive tutorial', 'pigz: A parallel implementation of gzip for multi-core machines', 'Podman: Pasta User-Mode Networking', 'Reverse Engineer’s Perspective on the Boeing 787 ‘51 days’ Directive', 'How to hide your IP address', "Dear JetBrains, Don't mess with your UI", 'Emulating double precision on the GPU to render large worlds', 'Does cashless society discriminate against the poor and elderly? (2019)', 'Is Truss Still PM?', 'Whipping up a new Shell – Lash#Cat9', 'The case for energy optimism', 'Cybersickness Could Spell an Early Death for the Metaverse', 'Compiling Swift Generics [pdf]', 'Revisiting the Playground', 'Postgres 15 Merge Command with Examples', 'Stability AI Raises $101M at $1B valuation', 'The rise and fall of second-hand bookshops in Britain', "Virding's First Rule of Programming (2008)", 'Solar-powered headphones', 'Ask HN: Have you ever heard of users demonstrating against software?']
['https://githubcopilotinvestigation.com/', 'https://www.daemonology.net/blog/2022-10-18-FreeBSD-Firecracker.html', 'https://blog.singleton.io/posts/2022-10-17-otp-on-wrist/', 'http://annas-blog.org/blog-how-to-become-a-pirate-archivist.html', 'https://www.hydro-international.com/content/news/seabed-2030-almost-25-of-world-s-seafloor-now-mapped', 'https://waxy.org/2022/09/ai-data-laundering-how-academic-and-nonprofit-researchers-shield-tech-companies-from-accountability/', 'https://sensebridge.net/projects/northpaw/', 'https://phys.org/news/2022-10-moon-slowly-drifting-earth-billion.html', 'https://newsletter.pragmaticengineer.com/p/real-world-engineering-challenges', 'https://reverbmachine.com/blog/trent-reznor-social-network-synth-sounds/', 'https://tigyog.app/d/H7XOvXvC_x/r/goedel-s-first-incompleteness-theorem', 'https://github.com/madler/pigz', 'https://github.com/containers/podman/pull/16141', 'https://ioactive.com/reverse-engineers-perspective-on-the-boeing-787-51-days-airworthiness-directive/', 'https://educatedguesswork.org/posts/traffic-relaying/', 'https://neil.computer/notes/dear-jetbrains-dont-mess-with-your-ui/', 'https://godotengine.org/article/emulating-double-precision-gpu-render-large-worlds', 'https://blogs.ischool.berkeley.edu/w231/2019/10/14/does-cashless-society-discriminate-against-the-poor-and-elderly/', 'https://is-truss-still-pm.uk/', 'https://arcan-fe.com/2022/10/15/whipping-up-a-new-shell-lashcat9/', 'https://syncretica.substack.com/p/the-case-for-energy-optimism', 'https://www.thedailybeast.com/cybersickness-could-spell-an-early-death-for-the-metaverse-and-virtual-reality', 'https://download.swift.org/docs/assets/generics.pdf', 'https://www.historyworkshop.org.uk/revisiting-the-playground/', 'https://www.crunchydata.com/blog/a-look-at-postgres-15-merge-command-with-examples', 'https://techcrunch.com/2022/10/17/stability-ai-the-startup-behind-stable-diffusion-raises-101m/', 'http://wormwoodiana.blogspot.com/2022/10/the-rise-and-fall-of-second-hand.html', 'http://rvirding.blogspot.com/2008/01/virdings-first-rule-of-programming.html', 'https://www.bbc.com/news/business-63211086', 'item?id=33238708']
[1134, 64, 80, 427, 282, 214, 295, 41, 22, 208, 342, 226, 26, 146, 173, 239, 107, 193, 5, 37, 79, 23, 75, 3, 127, 73, 41, 53, 35, 174]

 

 

특정한 정보 뽑아보기

# 가장 큰 투표를 받은 것의 타이틀과 링크 뽑기
largest_number = max(article_points)
largest_index = article_points.index(largest_number)
print(largest_index)

print(article_links[largest_index])
print(article_titles[largest_index])

>>0
https://githubcopilotinvestigation.com/
GitHub Copi­lot inves­ti­ga­tion