Getting Data
from collections import Counter
import math, random, csv, json, re
from bs4 import BeautifulSoup
import requests
์๋ฅผ ๋ค์ด, beautifulsoup ๊ฐ์, ์ด๋ค ๋ชจ๋์ด ์ค์น๋์ง ์์๋ค๋ฉด? ์ด๋ป๊ฒ ํด์ผ ํ ๊น์?
- googling: ์๋์ฝ๋ค beautifulsoup ์ค์น ๋ฐฉ๋ฒ
- ๊ตฌ๊ธ ๋ต๋ณ์์ ์๋์ฝ๋ค ํด๋ผ์ฐ๋๋ฅผ ์ฐพ์ผ์ธ์. ๋ชจ๋๋ค์ด ํ ์คํธ๋๊ณ ์์ ํ ๊ณณ์ ๋๋ค.
- ์ด์ , ์ฌ๋ฌ๋ถ์ ๋ถ๋๋ฌ์ด ์ ๋๋ก ๋ง์ ์๊ฐ์ acquiring(ํ๋), cleaning(์ ๋ฆฌ), and transforming data(๋ฐ์ดํฐ ๋ณํ)์ ํ ์ ํ๊ฒ ๋ ๊ฒ์ ๋๋ค.
stdin and stdout
Number of lines containing numbers
์ซ์๊ฐ ํฌํจ๋ ํ์ผ์ ํ ์๋ฅผ ์ ์ ์์ต๋๋ค.
sys.stdin(Keyboard) ๋ฐ sys.stdout(Monitor)์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ํ์ดํํ ์ ์์ต๋๋ค.
import sys, re
# sys.argv๋ ๋ช
๋ น์ค ์ธ์์ ๋ฆฌ์คํธ์
๋๋ค.
# sys.argv[0]์ ํ๋ก๊ทธ๋จ ์์ฒด์ ์ด๋ฆ์
๋๋ค.
# sys.argv[1]์ ๋ช
๋ น์ค์์ ์ง์ ํ ์ ๊ท ํํ์์ด ๋ ๊ฒ์
๋๋ค.
regex = sys.argv[1]
# ์คํฌ๋ฆฝํธ์ ์ ๋ฌ๋ ๊ฐ ์ค์ ๋ํด
for line in sys.stdin:
# ๋ง์ฝ ์ ๊ท ํํ์๊ณผ ์ผ์นํ๋ ๊ฒฝ์ฐ, ๊ทธ๊ฒ์ stdout์ ์๋๋ค.
if re.search(regex, line): # Regular Expression๊ณผ ๋ง๋ ๋ผ์ธ
sys.stdout.write(line)
- ๋ช ๋ น์ค์์ ์ฌ์ฉ์๊ฐ ์ง์ ํ ์ ๊ท ํํ์์ ์ด์ฉํ์ฌ ์ ๋ ฅ์ผ๋ก ๋ฐ์ ๊ฐ ์ค์ ๋ํด ๊ฒ์ํ๊ณ , ํด๋น ์ ๊ท ํํ์๊ณผ ์ผ์นํ๋ ๊ฒฝ์ฐ ํด๋น ์ค์ ํ์ค ์ถ๋ ฅ์ ์๋๋ค.
import sys
count = 0
# sys.stdin์์ ๊ฐ ์ค์ ์ฝ์ด๋ค์ฌ์
for line in sys.stdin:
# count ๋ณ์๋ฅผ ์ฆ๊ฐ์ํต๋๋ค.
count += 1
# print ํจ์๋ sys.stdout์ ์ถ๋ ฅ๋ฉ๋๋ค.
print(count)
0
# Windows
!type the_bible.txt | python egrep.py "[0-9]" | python line_count.py
/bin/bash: line 1: type: the_bible.txt: not found
python3: can't open file '/content/egrep.py': [Errno 2] No such file or directory
python3: can't open file '/content/line_count.py': [Errno 2] No such file or directory
Most Common Words
์ ๋ ฅ๋ ๋จ์ด๋ฅผ ์ธ์ด ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋จ์ด๋ฅผ ์์ฑํ๋ ์คํฌ๋ฆฝํธ ์ ๋๋ค.
import sys
from collections import Counter
# ์ฒซ ๋ฒ์งธ ์ธ์๋ก ๋จ์ด์ ์๋ฅผ ์ ๋ฌํฉ๋๋ค.
try:
num_words = int(sys.argv[1]) # ๋ช
๋ น์ด argument -> Command
except:
print("usage: most_common_words.py num_words")
sys.exit(1) # ๋น์ ์์ ์ข
๋ฃ ์ฝ๋๋ ์ค๋ฅ๋ฅผ ๋ํ๋
๋๋ค.
# ํ์ค ์
๋ ฅ์์ ๊ฐ ์ค์ ์ฝ์ด๋ค์ฌ์
# ์๋ฌธ์๋ก ๋ณํํ ๋จ์ด๋ฅผ ์นด์ดํธํฉ๋๋ค.
counter = Counter(word.lower() # ์๋ฌธ์๋ก ๋ณํ๋ ๋จ์ด
for line in sys.stdin # ํ์ค ์
๋ ฅ์ผ๋ก๋ถํฐ์ ๊ฐ ์ค
for word in line.strip().split() # ๊ณต๋ฐฑ์ผ๋ก ๋ถ๋ฆฌ๋ ๋จ์ด๋ค
if word) # ๋น '๋จ์ด'๋ ๊ฑด๋๋๋๋ค.
# ๊ฐ์ฅ ๋น๋๊ฐ ๋์ ๋จ์ด๋ฅผ ์ฐพ์ ์ถ๋ ฅํฉ๋๋ค.
for word, count in counter.most_common(num_words):
sys.stdout.write(str(count)) # ๋น๋๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
sys.stdout.write("\\t") # ํญ ๋ฌธ์๋ก ๊ตฌ๋ถํฉ๋๋ค.
sys.stdout.write(word) # ๋จ์ด๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
sys.stdout.write("\\n") # ์ค ๋ฐ๊ฟ ๋ฌธ์๋ก ์ค์ ๋ฐ๊ฟ๋๋ค.
# Windows
!type the_bible.txt | python most_common_words.py 10
64193 the
51380 and
34753 of
13643 to
12799 that
12560 in
10263 he
9840 shall
8987 unto
8836 for
Reading Files
The Basics of Text Files
# 'r'์ ์ฝ๊ธฐ ์ ์ฉ์ ์๋ฏธํฉ๋๋ค.
file_for_reading = open('reading_file.txt', 'r')
# 'w'๋ ์ฐ๊ธฐ๋ฅผ ์๋ฏธํฉ๋๋ค — ์ด๋ฏธ ํ์ผ์ด ์กด์ฌํ๋ฉด ํ์ผ์ ํ๊ดดํฉ๋๋ค!
file_for_writing = open('writing_file.txt', 'w')
# 'a'๋ ์ถ๊ฐ๋ฅผ ์๋ฏธํฉ๋๋ค — ํ์ผ ๋์ ์ถ๊ฐํฉ๋๋ค.
file_for_appending = open('appending_file.txt', 'a')
# ํ์ผ์ ์ฌ์ฉํ ํ์๋ ํ์ผ์ ๊ผญ ๋ซ์์ผ ํฉ๋๋ค.
file_for_writing.close() # Why? Open file ๊ฐ์๊ฐ ์ ํด์ ธ ์๊ธฐ ๋ผ๋ฌธ
- ํ์ผ์ ๋ซ๋ ๊ฒ์ ์๊ธฐ ์ฝ๊ธฐ ๋๋ฌธ์ ํญ์ ๋ธ๋ก๊ณผ ํจ๊ป ์ฌ์ฉํด์ผ ํ๋ฉฐ, ๋ธ๋ก์ด ๋๋๋ฉด ์๋์ผ๋ก ๋ซํ๋๋ค.
with open(filename, 'r') as f:
# 'f'๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
data = function_that_gets_data_from(f)
# ์ด ์์ ์์ 'f'๋ ์ด๋ฏธ ๋ซํ์ผ๋ฏ๋ก ์ฌ์ฉํ์ง ๋ง์ญ์์ค.
# ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
process(data)
starts_with_hash = 0
# 'input.txt' ํ์ผ์ ์ฝ๊ธฐ ๋ชจ๋๋ก ์ฝ๋๋ค.
with open('input.txt', 'r') as f:
# ํ์ผ์ ๊ฐ ์ค์ ํ์ธํฉ๋๋ค.
for line in f: # ํ์ผ์ ๊ฐ ์ค์ ํ์ธํฉ๋๋ค.
if re.match("^#", line): # ์ ๊ท์์ ์ฌ์ฉํ์ฌ ์ค์ด '#'๋ก ์์ํ๋์ง ํ์ธํฉ๋๋ค.
starts_with_hash += 1 # ๋ง์ฝ ๊ทธ๋ ๋ค๋ฉด, ์นด์ดํธ์ 1์ ๋ํฉ๋๋ค.
def get_domain(email_address):
"""'@'๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ถํ ํ๊ณ ๋ง์ง๋ง ๋ถ๋ถ์ ๋ฐํํฉ๋๋ค."""
return email_address.lower().split("@")[-1]
# 'email_addresses.txt' ํ์ผ์ ์ฝ๊ธฐ ๋ชจ๋๋ก ์ฝ๋๋ค.
with open('email_addresses.txt', 'r') as f:
# ํ์ผ์ ๊ฐ ์ค์ ๋ํด ๋๋ฉ์ธ์ ๊ฐ์ ธ์์ ์นด์ดํธํฉ๋๋ค.
# ์ฃผ์์ '@'๊ฐ ์๋ ์ค๋ง ์ฒ๋ฆฌํฉ๋๋ค.
domain_counts = Counter(get_domain(line.strip()) # ๊ฐ ์ค์ ๋๋ฉ์ธ์ ๊ฐ์ ธ์์
for line in f # ํ์ผ์ ๊ฐ ์ค์ ๋ํด
if "@" in line) # '@'๊ฐ ์๋ ์ค๋ง ์ฒ๋ฆฌํฉ๋๋ค.
Delimited Files
csv ํ์ผ : ์ด๋ฌํ ํ์ผ์ ์ผํ๋ก ๊ตฌ๋ถ๋๊ฑฐ๋ ํญ์ผ๋ก ๊ตฌ๋ถ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
!type tab_delimited_stock_prices.txt
6/20/2014 AAPL 90.91
6/20/2014 MSFT 41.68
6/20/2014 FB 64.5
6/19/2014 AAPL 91.86
6/19/2014 MSFT 41.51
6/19/2014 FB 64.34
- csv.reader๋ ์ค ๋จ์ ํํ ์์ฑ๊ธฐ์ ๋๋ค.
- ํญ์ผ๋ก ๊ตฌ๋ถ๋ ํ ์คํธ ํ์ผ์ ์ฝ์ด๋ค์ฌ์ ๊ฐ ํ์ ๋ ์ง, ๊ธฐํธ ๋ฐ ์ข ๊ฐ๋ฅผ ์ถ์ถํ๊ณ ์ถ๋ ฅํฉ๋๋ค.
- CSV ๋ชจ๋์ csv.reader() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ์ ํญ์ผ๋ก ๊ตฌ๋ถํ์ฌ ์ฝ์ต๋๋ค.
import csv
# 'tab_delimited_stock_prices.txt' ํ์ผ์ ์ฝ๊ธฐ ๋ชจ๋๋ก ์ฝ๋๋ค.
with open('tab_delimited_stock_prices.txt', 'r') as f:
# ํ์ผ์ ํญ์ผ๋ก ๊ตฌ๋ถํ์ฌ ์ฝ๋ CSV ๋ฆฌ๋๋ฅผ ์์ฑํฉ๋๋ค.
reader = csv.reader(f, delimiter='\\t')
# CSV ํ์ผ์ ๊ฐ ํ์ ๋ฐ๋ณตํ๋ฉด์
for row in reader:
# ๊ฐ ํ์ ์ด์ ์ถ์ถํฉ๋๋ค.
date = row[0] # ์ฒซ ๋ฒ์งธ ์ด: ๋ ์ง
symbol = row[1] # ๋ ๋ฒ์งธ ์ด: ๊ธฐํธ
closing_price = float(row[2]) # ์ธ ๋ฒ์งธ ์ด: ์ข
๊ฐ (๋ถ๋ ์์์ ์ผ๋ก ๋ณํ)
# ๋ ์ง, ๊ธฐํธ ๋ฐ ์ข
๊ฐ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
print(date, symbol, closing_price)
6/20/2014 AAPL 90.91
6/20/2014 MSFT 41.68
6/20/2014 FB 64.5
6/19/2014 AAPL 91.86
6/19/2014 MSFT 41.51
6/19/2014 FB 64.34
%%bash
cat colon_delimited_stock_prices.txt
date:symbol:closing_price
6/20/2014:AAPL:90.91
6/20/2014:MSFT:41.68
6/20/2014:FB:64.5
- ์ฝ๋ก ์ผ๋ก ๊ตฌ๋ถ๋ ํ ์คํธ ํ์ผ์ ์ฝ์ด๋ค์ฌ์ ๊ฐ ํ์ ๋ ์ง, ๊ธฐํธ ๋ฐ ์ข ๊ฐ๋ฅผ ์ถ์ถํ๊ณ ์ถ๋ ฅํฉ๋๋ค.
- CSV ๋ชจ๋์ csv.DictReader() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ์ ์ฝ๊ณ , ๊ฐ ํ์ ๋์ ๋๋ฆฌ๋ก ๋ํ๋ ๋๋ค.
import csv
# 'colon_delimited_stock_prices.txt' ํ์ผ์ ์ฝ๊ธฐ ๋ชจ๋๋ก ์ฝ๋๋ค.
with open('colon_delimited_stock_prices.txt', 'r') as f:
# ํ์ผ์ ์ฝ๋ก ์ผ๋ก ๊ตฌ๋ถํ์ฌ ์ฝ๋ CSV ๋์
๋๋ฆฌ ๋ฆฌ๋๋ฅผ ์์ฑํฉ๋๋ค.
reader = csv.DictReader(f, delimiter=':')
# CSV ํ์ผ์ ๊ฐ ํ์ ๋ฐ๋ณตํ๋ฉด์
for row in reader:
# ๊ฐ ํ์ ํ๋ ๊ฐ์ ๋์
๋๋ฆฌ์์ ์ถ์ถํฉ๋๋ค.
date = row["date"] # 'date' ํ๋
symbol = row["symbol"] # 'symbol' ํ๋
closing_price = float(row["closing_price"]) # 'closing_price' ํ๋ (๋ถ๋ ์์์ ์ผ๋ก ๋ณํ)
# ๋ ์ง, ๊ธฐํธ ๋ฐ ์ข
๊ฐ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
print(date, symbol, closing_price)
6/20/2014 AAPL 90.91
6/20/2014 MSFT 41.68
6/20/2014 FB 64.5
%%bash
cat comma_delimited_stock_prices.txt
FB,64.5
MSFT,41.68
AAPL,90.91
- ์ค๋์ ์ฃผ๊ฐ๋ฅผ ๋ํ๋ด๋ ๋์ ๋๋ฆฌ๋ฅผ ์ฝค๋ง๋ก ๊ตฌ๋ถ๋ ํ ์คํธ ํ์ผ์ ์ฐ๋ ์์ ์ ๋๋ค.
- CSV ๋ชจ๋์ csv.writer() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ์ ์ฐ๊ณ , ๊ฐ ์ฃผ์๊ณผ ๊ฐ๊ฒฉ์ ๋ฆฌ์คํธ๋ก ๋ง๋ค์ด์ ํ์ผ์ ์๋๋ค.
import csv
# ์ค๋์ ์ฃผ๊ฐ๋ฅผ ๋ํ๋ด๋ ๋์
๋๋ฆฌ์
๋๋ค.
today_prices = {'AAPL': 90.91, 'MSFT': 41.68, 'FB': 64.5}
# 'comma_delimited_stock_prices_1.txt' ํ์ผ์ ์ฐ๊ธฐ ๋ชจ๋๋ก ์ฝ๋๋ค.
with open('comma_delimited_stock_prices_1.txt', 'w') as f:
# ํ์ผ์ ์ฝค๋ง๋ก ๊ตฌ๋ถํ์ฌ ์ฐ๋ CSV ๋ผ์ดํฐ๋ฅผ ์์ฑํฉ๋๋ค.
writer = csv.writer(f, delimiter=',')
# ์ค๋์ ์ฃผ๊ฐ ๋์
๋๋ฆฌ์์ ๊ฐ ์ฃผ์๊ณผ ๊ฐ๊ฒฉ์ ๊ฐ์ ธ์์ ํ์ผ์ ์ฐ๊ธฐํฉ๋๋ค.
for stock, price in today_prices.items():
# ๊ฐ ์ฃผ์๊ณผ ๊ฐ๊ฒฉ์ ๋ฆฌ์คํธ๋ก ๋ง๋ค์ด์ ์ฐ๊ธฐํฉ๋๋ค.
writer.writerow([stock, price])
%%bash
cat comma_delimited_stock_prices_1.txt
AAPL,90.91
MSFT,41.68
FB,64.5
results = [["test1", "success", "Monday"],
["test2", "success, kind of", "Tuesday"],
["test3", "failure, kind of", "Wednesday"],
["test4", "failure, utter", "Thursday"]]
# don't do this!
with open('bad_csv.txt', 'w') as f:
for row in results:
f.write(",".join(map(str, row))) # might have too many commas in it!
f.write("\\n") # row might have newlines as well!
%%bash
cat bad_csv.txt
test1,success,Monday
test2,success, kind of,Tuesday
test3,failure, kind of,Wednesday
test4,failure, utter,Thursday
Scraping the Web
๋ฐ์ดํฐ๋ฅผ ์ป๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์น ํ์ด์ง์์ ์คํฌ๋ฉํ๋ ๊ฒ์ ๋๋ค
HTML & Parsing
<html>
<head>
<title>A web page</title>
</head>
<body>
<p id="author">Joel Grus</p>
<p id="subject">Data Science</p>
</body>
</html>
- for python3:
!pip install html5lib
!pip install beautifulsoup4
- for anaconda
conda install -c anaconda html5lib
conda install -c anaconda beautifulsoup4
DOM Lesson One
- Hello World! - John | Doe | Alaska
from bs4 import BeautifulSoup
html = """
<html>
<head>
<title>A web page</title>
</head>
<body>
<p id="author">Joel Grus</p>
<p id="subject">Data Science</p>
<p class="price">30</p>
</body>
</html>"""
soup = BeautifulSoup(html, 'html5lib')
์ค์: Tag, Attribute, Text
soup = BeautifulSoup(html, 'html5lib')→ Parsing ํด์ ์๋ฃ๊ตฌ์กฐํ ํฉ๋๋ค.(Dict ํ)
Query 1: Find title (์ ๋ชฉ ์ฐพ๊ธฐ)
soup.title.text
# 'A web page'
Query 2: Find title's text (์ ๋ชฉ ํ ์คํธ ์ฐพ๊ธฐ)
soup.title.text
# 'A web page'
Query 3: Find p of body (p์ ๋ณธ๋ฌธ ์ฐพ๊ธฐ)
soup.body.p
# <p id="author">Joel Grus</p>
Query 4: Find all p under body (p์๋ ๋ณธ๋ฌธ ์ฐพ๊ธฐ)
soup.body('p')
[<p id="author">Joel Grus</p>,
<p id="subject">Data Science</p>,
<p class="price">30</p>]
Query 5: Find second p's text of body (๋ ๋ฒ์งธ p์ ๋ณธ๋ฌธ ์ฐพ๊ธฐ)
soup.body('p')[1].text
# 'Data Science'
Query 6: Find last p of body (p์ ๋ง์ง๋ง ๋ถ๋ถ ์ฐพ๊ธฐ)
soup.body('p')[-1]
# <p class="price">30</p>
Query 7: Loop over all p of body (p์ ๋ชจ๋ ๋ถ๋ถ์ ๋ฃจํ๋ฅผ ์์ฐ๊ธฐ)
for i, p in enumerate(soup.body('p')):
print('paragraph {}: {}'.format(i, p.text))
paragraph 0: Joel Grus
paragraph 1: Data Science
paragraph 2: 30
Query 8: Find first p's id attribute's value (์ฒซ ๋ฒ์งธ p์ ID ์์ฑ ๊ฐ ์ฐพ๊ธฐ)
soup.p['id']
# 'author'
Query 9: Find all p whose attribute id is 'author' (์์ฑ ID๊ฐ '์ ์'์ธ ๋ชจ๋ p ์ฐพ๊ธฐ)
soup('p', {'id':'author'})
# [<p id="author">Joel Grus</p>]
Query 10: Find all p whose attribute class is 'price' (์์ฑ ํด๋์ค๊ฐ '๊ฐ๊ฒฉ'์ธ ๋ชจ๋ p ์ฐพ๊ธฐ)
soup('p', 'price')
#soup('p', {'class':'price'})
[<p class="price">30</p>]
Query 11: Find all texts (๋ชจ๋ ํ ์คํธ ์ฐพ๊ธฐ)
soup.text # List
# '\\n A web page\\n \\n \\n Joel Grus\\n Data Science\\n 30\\n \\n'
first_paragraph = soup.find('p') # ๋๋ soup.p
print(first_paragraph) # ์ฒซ ๋ฒ์งธ <p> ํ๊ทธ์ ๋ด์ฉ์ ์ถ๋ ฅํฉ๋๋ค.
print(type(first_paragraph)) # ๊ฒฐ๊ณผ์ ํ์
์ ์ถ๋ ฅํฉ๋๋ค.
<p id="author">Joel Grus</p>
<class 'bs4.element.Tag'>
- ์ฒซ ๋ฒ์งธ <p> ํ๊ทธ์ ๋ด์ฉ์ด ๋ค์ด ์์ ๊ฒ์ด๋ฉฐ, <p> ํ๊ทธ ๋ด์ฉ์ ํ์ ์ BeautifulSoup์ ํน์ํ ํ์ ์ธ Tag ์ ๋๋ค.
first_paragraph_text = soup.p.text
first_paragraph_text
# 'Joel Grus'
first_paragraph_words = soup.p.text.split()
first_paragraph_words
# ['Joel', 'Grus']
- ์ฒซ ๋ฒ์งธ <p> ํ๊ทธ์ ํ ์คํธ ๋ด์ฉ์ ์ถ์ถํ ํ, .split() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ณต๋ฐฑ์ ๊ธฐ์ค์ผ๋ก ๋จ์ด ๋จ์๋ก ๋ถํ ํฉ๋๋ค.
first_paragraph_id = soup.p['id'] # 'id' ์์ฑ์ด ์์ผ๋ฉด KeyError๋ฅผ ๋ฐ์์ํต๋๋ค.
first_paragraph_id
#type(soup.p)
# Result: 'author'
- soup์์ ์ฒซ ๋ฒ์งธ <p> ํ๊ทธ์ id ์์ฑ ๊ฐ์ ๊ฐ์ ธ์์ first_paragraph_id ๋ณ์์ ํ ๋นํฉ๋๋ค.
- ๋ง์ฝ ํด๋น ํ๊ทธ์ id ์์ฑ์ด ์๋ค๋ฉด KeyError๊ฐ ๋ฐ์ํฉ๋๋ค.
first_paragraph_id2 = soup.p.get('id') # 'id' ์์ฑ์ด ์์ผ๋ฉด None์ ๋ฐํํฉ๋๋ค.
print(first_paragraph_id2)
# Result: 'author'
- soup์์ ์ฒซ ๋ฒ์งธ <p> ํ๊ทธ์ id ์์ฑ ๊ฐ์ ๊ฐ์ ธ์์ first_paragraph_id2 ๋ณ์์ ํ ๋นํฉ๋๋ค.
- ๋ง์ฝ ํด๋น ํ๊ทธ์ id ์์ฑ์ด ์๋ค๋ฉด None์ ๋ฐํํฉ๋๋ค.
all_paragraphs = soup.find_all('p') # ๋๋ soup('p')๋ก๋ ๊ฐ๋ฅํฉ๋๋ค.
print(all_paragraphs)
[<p id="author">Joel Grus</p>, <p id="subject">Data Science</p>]
- soup์์ ๋ชจ๋ <p> ํ๊ทธ๋ฅผ ์ฐพ์์ all_paragraphs ๋ณ์์ ํ ๋นํฉ๋๋ค.
- ๊ทธ ๊ฒฐ๊ณผ๋ ๋ฆฌ์คํธ ํํ๋ก ๋ฐํ๋ฉ๋๋ค.
soup('p')
# [<p id="author">Joel Grus</p>, <p id="subject">Data Science</p>]
soup('p', {'id':'subject'})
# [<p id="subject">Data Science</p>]
- id ์์ฑ์ด 'subject'์ธ ๋ชจ๋ <p> ํ๊ทธ๋ฅผ ์ฐพ๋ ์์์ ๋๋ค.
- ๊ฒฐ๊ณผ๋ ํด๋น ์กฐ๊ฑด์ ๋ง๋ <p> ํ๊ทธ๋ค์ ํฌํจํ๋ ๋ฆฌ์คํธ๋ก ๋ฐํํฉ๋๋ค.
- soup์์ id ์์ฑ์ด 'subject' ์ธ ๋ชจ๋ <p> ํ๊ทธ๋ฅผ ์ฐพ์ ๋ฐํํฉ๋๋ค.
- ๋ ๋ฒ์งธ ์ธ์๋ก๋ ๋์ ๋๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ ์์ฑ๊ณผ ๊ทธ ๊ฐ์ ์กฐ๊ฑด์ ์ง์ ํฉ๋๋ค.
paragraphs_with_ids = [p for p in soup('p') if p.get('id')]
paragraphs_with_ids
[<p id="author">Joel Grus</p>, <p id="subject">Data Science</p>]
- BeautifulSoup ๊ฐ์ฒด soup์์ ๋ชจ๋ <p> ํ๊ทธ๋ฅผ ์ฐพ์ ํ, ๋ฆฌ์คํธ ์ปดํ๋ฆฌํจ์ ์ ์ฌ์ฉํ์ฌ id ์์ฑ์ ๊ฐ์ง ํ๊ทธ๋ค๋ง ๋ชจ์์ paragraphs_with_ids ๋ฆฌ์คํธ์ ์ ์ฅํฉ๋๋ค.
- ๊ฒฐ๊ณผ๋ id ์์ฑ์ ๊ฐ์ง <p> ํ๊ทธ๋ค์ ๋ฆฌ์คํธ๋ก ๋ฐํ๋ฉ๋๋ค.
important_paragraphs = soup('p', {'class': 'important'})
# [<p id="author">Joel Grus</p>, <p id="subject">Data Science</p>]
- soup์์ ํด๋์ค๊ฐ 'important'์ธ ๋ชจ๋ <p> ํ๊ทธ๋ฅผ ์ฐพ์ ๋ฐํํฉ๋๋ค.
- ๋ ๋ฒ์งธ ์ธ์๋ก๋ ๋์ ๋๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ ํด๋์ค์ ๊ทธ ๊ฐ์ ์กฐ๊ฑด์ ์ง์ ํฉ๋๋ค.
# ๋ค์ด๋ฒ ํํ์ด์ง์ HTML์ ๊ฐ์ ธ์ต๋๋ค.
html = requests.get("<http://www.naver.com>").text
# HTML์ BeautifulSoup์ผ๋ก ํ์ฑํฉ๋๋ค.
soup = BeautifulSoup(html, 'html5lib')
- requests ๋ชจ๋์ ์ฌ์ฉํ์ฌ ๋ค์ด๋ฒ ํํ์ด์ง์ GET ์์ฒญ์ ๋ณด๋ด๊ณ , ํด๋น ํ์ด์ง์ HTML์ ๊ฐ์ ธ์ต๋๋ค.
- ๊ทธ ํ, BeautifulSoup์ ์ฌ์ฉํ์ฌ HTML์ ํ์ฑํ์ฌ ๊ฐ์ฒด๋ก ์ ์ฅํฉ๋๋ค.
- ์ด๋ ๊ฒ ํ๋ฉด ์น ํ์ด์ง์ ๊ตฌ์กฐ๋ฅผ ํ์ํ๊ณ ์ํ๋ ์ ๋ณด๋ฅผ ์ถ์ถํฉ๋๋ค.
# ๊ฒฝ๊ณ : ๋ง์ฝ <span>์ด ์ฌ๋ฌ ๊ฐ์ <div> ์์ ์๋ ๊ฒฝ์ฐ, ๊ฐ์ <span>์ ์ฌ๋ฌ ๋ฒ ๋ฐํํ ์ ์์ต๋๋ค.
# ๋ง์ฝ ๊ทธ๋ ๋ค๋ฉด ์ข ๋ ๋๋ํ๊ฒ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
spans_inside_divs = [span # <span>์ ๊ฐ๊ฐ ๋ฆฌ์คํธ์ ์ถ๊ฐํฉ๋๋ค.
for div in soup('div') # ํ์ด์ง์ ๊ฐ <div>์ ๋ํด
for span in div('span')] # ๊ทธ ์์ ์๋ ๊ฐ <span>์ ์ฐพ์ต๋๋ค.
- soup์์ ๋ชจ๋ <div> ํ๊ทธ๋ฅผ ์ฐพ์ ํ, ๊ฐ <div> ํ๊ทธ ์์ ์๋ ๋ชจ๋ <span> ํ๊ทธ๋ฅผ ์ฐพ์ ๋ฆฌ์คํธ์ ์ถ๊ฐํฉ๋๋ค.
- ๊ทธ๋ฌ๋ ๋ง์ฝ <span> ํ๊ทธ๊ฐ ์ฌ๋ฌ ๊ฐ์ <div> ํ๊ทธ ์์ ์กด์ฌํ๋ ๊ฒฝ์ฐ, ๋์ผํ <span>์ ์ฌ๋ฌ ๋ฒ ๋ฐํํฉ๋๋ค.
spans_inside_divs
- spans_inside_divs ๋ณ์์๋ ๋ชจ๋ <div> ํ๊ทธ ์์ ์๋ ๋ชจ๋ <span> ํ๊ทธ๊ฐ ํฌํจ๋ ๋ฆฌ์คํธ๊ฐ ์ ์ฅ๋์ด ์์ ๊ฒ์ ๋๋ค.
- ์ด ๋ฆฌ์คํธ๋ ๊ฐ <div> ํ๊ทธ์ ๋ํด ๊ทธ ์์ ์๋ ๋ชจ๋ <span> ํ๊ทธ๋ฅผ ํฌํจํ๊ณ ์์ต๋๋ค.
- ์ด ๋ฆฌ์คํธ๋ฅผ ์ถ๋ ฅํ๋ฉด ํด๋น ์ ๋ณด๋ฅผ ํ์ธํฉ๋๋ค.
'๐ Data Mining' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Data Mining] Gradient Descent (๊ฒฝ์ฌ ํ๊ฐ๋ฒ) (0) | 2024.07.23 |
---|---|
[Data Mining] Statistics (ํต๊ณํ) (0) | 2024.07.14 |
[Data Mining] Linear Algebra (์ ํ๋์) (0) | 2024.07.09 |
[Data Mining] Introduction to Numpy part.2 (0) | 2024.07.05 |
[Data Mining] Introduction to Numpy part.1 (0) | 2024.06.26 |