python์ ์ด์ฉํ ํด๋ฆฌ์ ํ์๋ง๋ค๊ธฐ - BeautifulSoup ์ฌ์ฉํธ
์ง๋ HTML ๋ถ์ํธ์์ ํ์ธํ๋ฏ์ด ์ฐ๋ฆฌ๋ <td class="mytr">์ ๊ฐ์ ธ์ category,subject,post_name ์ด 3๊ฐ์ง๋ฅผ ์ถ๋ ฅํ๋ ค๊ณ ํฉ๋๋ค. ์ฐ์ BeautifulSoup๋ฅผ ์ค์นํด์ผ๊ฒ ์ง์?
pip install BeaautifulSoup4
BeautifulSoup์์ third-party Python parser์ธ lxml๊ณผ html5lib๋ ์ง์ํ์ง๋ง ์ ๋ Python์ ๊ธฐ๋ณธ ๋ด์ฅ ํ์๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํฉ๋๋ค.
from bs4 import BeautifulSoup from urllib.request import Request,rulopen from urllib.paarse import urljoin
์ฒซ from bs4 import BeautifulSoup์ BeautifulSoup๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์ถ๊ฐํด์ฃผ๋๊ฒ์ด๋ฉฐ from urllib.request importRequest,urlopen ์ url์ ์ด์ฉํ์ฌ ํด๋น ํ์ด์ง์ ์ ์ํ๊ธฐ ์ํด ์ถ๊ฐํด ์ค๋๋ค. ๋ง์ง๋ง from urllib.parse import urljoin์ ๋ค์๊ณผ ๊ฐ์ด ํด๋น ๊ธ์ url์ ์๋๊ฒฝ๋ก๋ก ํ์๋์ด์์ต๋๋ค. ์ด๋ฅผ ์ ๋๊ฒฝ๋ก๋ก ๋ณ๊ฒฝํ์ฌ ์ฃผ๊ธฐ ์ํ์ฌ ์ถ๊ฐํด ์ค๋๋ค.
clien ํ๊ณผ๊ฐ์ข ๊ฒ์ํ ์ ์ํ๊ธฐ
์ฐ์ clien ํ๊ณผ๊ฐ์ข ๊ฒ์ํ์ ์ฌ๋ ์ฝ๋๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
base_url = "http://www.clien.net/cs2/bbs/board.php?bo_table=lecture" url_request = Request(base_url,headers={'User-Agent': 'Mozilla/5.0'}) clien_tip_board = urlopen(url_request).read()
Request์ headers={'User-Agent': 'Mozilla/5.0'}๋ ์ ์ด์ฃผ์์ง ์์ผ๋ฉด ๋ด์ผ๋ก ๊ฐ์ฃผํ์ฌ ํด๋น ํ์ด์ง๋ฅผ ์ด์ ์๊ฒ ํ๋๊ฒฝ์ฐ๊ฐ ์๊ธฐ์ User-Agent๋ฅผ ์กฐ์ํ์ฌ ์ ์์ ํ๊ฒ ๋ฉ๋๋ค.
์ด๊ณณ๊น์ง ์์ฑํ์๋ค๋ฉด ์ฐ๋ฆฌ๋ clien ํ๊ณผ๊ฐ์ข ๊ฒ์ํ์ ๊ฐ์ ธ์ค๋๋ฐ ์ฑ๊ณตํ์์ต๋๋ค : ^)
BeautifulSoup์ ์ด์ฉํ์ฌ ์ํ๋ ๋ถ๋ถ ์ถ๋ ฅํ๊ธฐ
์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก BeautifulSoup์ ์ด์ฉํ์ฌ ์ํ๋ ๋ถ๋ถ๋ค๋ง ๊ฐ์ ธ์์ ์ถ๋ ฅ์ ํ๋ฉด๋ฉ๋๋ค.
bs4_clien = BeautifulSoup(clien_tip_board,"html.parser") find_mytr = bs4_clien.find_all("tr",attrs={'class':"mytr"}) for t in find_mytr: print(t.find('td',attrs={'class':'post_category'}).get_text(strip=True)) print("์ ๋ชฉ : "+t.find('td',attrs={'class':'post_subject'}).get_text(strip=True).encode('cp949','ignore').decode('cp949')) print("url : "+urljoin(base_url,t.find('td',attrs={'post_subject'}).a.get('href'))) print("๊ธ์ด์ด : "+t.find('td',attrs={'class' : 'post_name'}).get_text(strip=True))
์ฐ์ ์ find_all()ํจ์๋ฅผ ์ฌ์ฉํ ๊ฒ์ธ๋ฐ์. bs4_clien.find_all() ํจ์๋ find_all ๋ง๊ทธ๋๋ก bs_clien์์ ํด๋นํ๋๊ฒ๋ค์ ๋ชจ๋ ๊ฐ์ ธ ์ค๋ ํจ์์
๋๋ค. ์ฐ๋ฆฌ๋ 1ํ์ด์ง์ ๋ชจ๋ </td><tr class="mytr">์ ๊ฐ์ ธ์ค๊ธฐ๋ก ํ์์ต๋๋ค. ๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๊ฐ ํ์ํฉ๋๋ค.
find_mytr = bs4_clien.find_all("tr",attrs={'class':"mytr"})
๋ค์์ ์ด์ mytr์ ๊ฐ์ ธ์์ผ๋ ๊ทธ์์ ์๋ post_category,post_subject,post_name์ ๊ฐ์ ธ ์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
for t in find_mytr: print(t.find('td',attrs={'class':'post_category'}).get_text(strip=True)) print("์ ๋ชฉ : "+t.find('td',attrs={'class':'post_subject'}).get_text(strip=True).encode('cp949','ignore').decode('cp949')) print("url : "+urljoin(base_url,t.find('td',attrs={'post_subject'}).a.get('href'))) print("๊ธ์ด์ด : "+t.find('td',attrs={'class' : 'post_name'}).get_text(strip=True))
๋ค ๊ณตํต๋ ๋ถ๋ถ์ธ๋ฐ์ find()ํจ์๋ ํด๋นํ๊ฒ์ ๊ฐ์ ธ์ค๋ ํจ์์
๋๋ค. find_all()ํจ์์๋ ๋ค๋ฅด๊ฒ ์ฒซ๋ฒ์งธ๊ฒ๋ง์ ๊ฐ์ ธ์ค๊ธฐ๋๋ฌธ์ ์ฒซ๋ฒ์งธ๊ฒ ํ๋๋ง ํ์ํ๊ฒ ๋๋ฉด ํจ์ฌ ํจ์จ์ ์ธ ์ฝ๋๊ฐ ๋๊ฒ ์ง์.
<td class="post_category">๋ฅผ ๊ฐ์ ธ์ค๊ธฐ์ํ์ฌ
find('td',attrs={'class':'post_category'})
๋ฅผ ์ฌ์ฉํ์์ต๋๋ค. ๊ทธ๋ค .get_text(strip=True)๋ ํด๋นํ๊ทธ ์์์๋ ํ
์คํธ๋ฅผ ๊ฐ์ ธ์ค๋ ํจ์์ธ๋ฐ์ strip=True๋ ์๋ค๊ณต๋ฐฑ๋ฌธ์๋ฅผ ์ง์์ฃผ๋ ์ต์
์
๋๋ค.
</td><td class="post_subject"> ๋ ๋ง์ฐฌ๊ฐ์ง๋ก find()ํจ์์ get_text()ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ธ์ต๋๋ค.
url์ฃผ์๋ </td><td class="post_subject"> ํ๊ทธ ์์์๋ <a href=""> ์ ์กด์ฌํ๊ณ ์์ต๋๋ค. ๋ฐ๋ผ์ t.find('td',attrs={'post_subject'}).a.get('href')์ด๋ฌํ ๋ฐฉ๋ฒ์ผ๋ก url ์ฃผ์๋ฅผ ๊ฐ์ ธ์ค๊ฒ ๋ฉ๋๋ค. findํจ์๋ก </a></td><td class="post_subject">๋ฅผ ๊ฐ์ ธ์ค๊ณ ๊ทธ์์ ์๋ a ํ๊ทธ์ href๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์
๋๋ค. ์์์ ๋งํ๋ฏ ์ด๊ณณ์ ์๋๊ฒฝ๋ก์ธ ../~๋ก ์์๋ ์ฃผ์๊ฐ ํฌํจ๋์ด์๋๋ฐ์. ์ด๊ฒ์ ์ ๋๊ฒฝ๋ก ์ฆ ์ฐ๋ฆฌ๊ฐ ์ ์ํ๋ ์ฃผ์๋ก ๋ฐ๊ฟ์ฃผ๋ ํจ์๊ฐ ๋ฐ๋ก ์ฒ์์ ์ถ๊ฐํด์ฃผ์๋ urljoin()ํจ์์
๋๋ค.
์ ์ด์ Clien ํ๊ณผ๊ฐ์ข ๊ฒ์ํ์ ํ์ฑํ๋ ๋ฒ์ด ๋๋ฌ์ต๋๋ค. ์ ์ ์ฌ๋ฆฐ ํธ์ํฐ๊ฐ์ข์ ์ฐ๊ณํ์ฌ ์ฌ์ฉํ๋ค๋ฉด ์์ ์ด ์ํ๋ ๊ธ์ด ์ฌ๋ผ์ค๋ฉด Twitter๋ฅผ ํตํ์ฌ DM์ผ๋ก ๋ฐ์ ์ ์๊ฒ ๋ค์.
์ ๋ชฉ๋ถ๋ถ์ encodeํ decode๋ฅผ ํ์๋๋ฐ์. ์ฌ์ค ์ด๊ฒ๋๋ฌธ์ BeautifulSoupํธ ๊ฐ์ข๊ฐ ๋ฆ์ด์ก์ต๋๋ค. ์ ๋ ์๋์ฐ๋ฅผ ์ฌ์ฉํ๊ธฐ๋๋ฌธ์ cmd์ฐฝ์์ cp949๋ฅผ ์ฌ์ฉํ์ฌ ์ถ๋ ฅ์ํ๋๋ฐ ํ๋ถ์ด ๊ฐ์ข๋ฅผ ์ฌ๋ ค์ฃผ์ ๊ธ์ cp949์์ ์๋ ๊ธ์์ธ์ง ์๊พธ ์ค๋ฅ๋ฅผ ๋ฟ๋๊ตฐ์. ๊ทธ๋์ cp949๋ก ์ธ์ฝ๋ฉ์ ํ๋ฉฐ ์๋ ๋ฌธ์๋ ๊ทธ๋ฅ ์ ๊ฑฐ๋ฅผ ํด๋ฒ๋ ธ์ต๋๋ค.