[Python] 판다스(pandas)_9. 웹 데이터 추출(read_xml, read_html, BeautifulSoup)
#정리
**트리(tree) : 하나의 원점에서 출발하여, 하위 노드들이 여러 계층을 이루며 뻗어나가는 자료 형태를 비선형적 자료 구조.
#19readxml - xml코드 데이터 추출
# url 접속 후, xml(앨범 더미정보) 불러오기
# xml 데이터 추출(ElementTree 라이브러리로 읽어들이기)
** DataFrame.read_xml( )로 읽어 올 수도 있지만, 강사님은 별도의 방법으로 데이터 재정리
- import xml.etree.ElementTree as ET
- 데이터 추출 및 데이터 프레임으로 변경
#20read_html - html코드 속 데이터 추출
# url 접속 후, html(웹페이지 정보) 불러오기
# 웹페이지 데이터 추출(표 데이터 읽어들이기)
** DataFrame.read_html( )로 읽어 올 수도 있지만, 강사님은 별도의 방법으로 데이터 재정리
#from lxml.html import parse
#from io import StringIO
#데이터 추출 및 데이터 프레임으로 변경#21read_html_bs4 - 웹페이지 파싱 라이브러리
#from bs4 import BeautifulSoup
#from urllib.request import urlopen
#from urllib.parse import quote
<URL(동아일보) 응답 받기>- url = "http://www.donga.com/news/search?query=python"
- str_text = urlopen(url).read().decode('utf-8') #코드 형태로 응답 수령<뉴스 별 링크 추출하기>
- soup = BeautifulSoup(str_text,features="lxml")
- rs = soup.find_all('p',{'class':'tit'})#p태그의 tit 속성만 추출 <p class="tit">
- 뉴스 기사별 url추출<뉴스 기사 내용 추출하기>
#UTF-8 파싱에러 발생시 아래 코드로 변경
**트리(tree) : 하나의 원점에서 출발하여, 하위 노드들이 여러 계층을 이루며 뻗어나가는 자료 형태를 비선형적 자료 구조.
#19readxml - xml코드 속 데이터 추출
# url 접속 후, 앨범 더미정보 불러오기
import requests
url = "https://www.w3schools.com/xml/cd_catalog.xml"
response = requests.get(url)
str_text = response.content.decode("utf-8")
print(str_text) #str
# xml 데이터 추출(ElementTree 라이브러리로 읽어들이기)
** DataFrame.read_xml( )로 읽어 올 수도 있지만, 강사님은 별도의 방법으로 데이터 재정리
- import xml.etree.ElementTree as ET
- 데이터 추출 및 데이터 프레임으로 변경
#데이터 추출
root = ET.fromstring(str_text)
list_dict = []
#데이터 리스트화 (데이터 프레임에 넣기 위해)
for node in root:
list_dict.append({
"TITLE":node.find('TITLE').text,
"ARTIST":node.find('ARTIST').text,
"COUNTRY":node.find('COUNTRY').text,
"COMPANY":node.find('COMPANY').text,
"PRICE":node.find('PRICE').text,
"YEAR":node.find('YEAR').text,
})
#데이터 프레임으로 변경
df = pd.DataFrame(list_dict)
print(df)
--예문 코드 보기--
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
print("---------------")
import requests
print("--response------")
#앨범 더미정보 불러오기
url = "https://www.w3schools.com/xml/cd_catalog.xml"
response = requests.get(url)
str_text = response.content.decode("utf-8")
print(str_text) #str
print("---------------")
import xml.etree.ElementTree as ET
#print(pd.read_xml(str_text))
#더미 데이터의 구조를 트리구조라고 한다.
root = ET.fromstring(str_text) #ET : Elemental Tree
print(root) #root : CATALOG
print("---------------")
list_dict = []
for node in root:
#print(node) #node : CD
#print(node.find('TITLE')) #TITLE
print(node.find('TITLE').text) #Empire Burlesque
print(node.find('ARTIST').text) #Bob Dylan
print(node.find('COUNTRY').text)
print(node.find('COMPANY').text)
print(node.find('PRICE').text)
print(node.find('YEAR').text)
print("---------------")
print("---------------")
for node in root:
list_dict.append({
"TITLE":node.find('TITLE').text,
"ARTIST":node.find('ARTIST').text,
"COUNTRY":node.find('COUNTRY').text,
"COMPANY":node.find('COMPANY').text,
"PRICE":node.find('PRICE').text,
"YEAR":node.find('YEAR').text,
})
df = pd.DataFrame(list_dict)
print(df)
#20read_html - html코드 속 데이터 추출
# url 접속 후, 웹페이지 정보 불러오기
print("--response------")
url = "https://www.w3schools.com/html/html_tables.asp"
response = requests.get(url)
str_text = response.content.decode("utf-8")
print(str_text) #str
# 웹페이지 데이터 추출(표 데이터 읽어들이기)
** DataFrame.read_html( )로 읽어 올 수도 있지만, 강사님은 별도의 방법으로 데이터 재정리
#from lxml.html import parse
#from io import StringIO
#데이터 추출 및 데이터 프레임으로 변경
html_DOC = parse(StringIO(str_text))
first_table = html_DOC.getroot().findall('.//table')[0] #페이지 속 테이블(표) 찾기
list_ths = first_table.findall('.//th') #테이블 제목 추출
column_names = [] #테이블 컬럼 추출
for th in list_ths:
#print(th.text_content())
column_names.append(th.text_content())
#print(column_names)
list_tds = first_table.findall('.//td') #테이블 데이터 추출
#print(list_tds)
datas = []
for td in list_tds:
#print(td.text_content())
datas.append(td.text_content())
#print(datas)
arr = np.array(datas).reshape(int(len(datas)/len(column_names)),len(column_names))
print(pd.DataFrame(arr,columns=column_names))
--예문 코드 보기--
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
import requests
print("--response------")
url = "https://www.w3schools.com/html/html_tables.asp"
response = requests.get(url)
str_text = response.content.decode("utf-8")
print(str_text) #str
print("---------------")
#print(pd.read_html(str_text))
from lxml.html import parse
from io import StringIO
html_DOC = parse(StringIO(str_text))
print(html_DOC)
print("---------------")
print(html_DOC.getroot().findall('.//table'))
print("---#페이지 속 테이블(표) 찾기-----")
#페이지 속 테이블(표) 찾기
first_table = html_DOC.getroot().findall('.//table')[0]
print(first_table)
print("--#테이블 제목 추출---")
#테이블 제목 추출
list_ths = first_table.findall('.//th')
print(list_ths)
print("---#테이블 컬럼 추출----")
#테이블 컬럼 추출
column_names = []
for th in list_ths:
#print(th.text_content())
column_names.append(th.text_content())
print(column_names)
print("---#테이블 데이터 추출----")
list_tds = first_table.findall('.//td')
print(list_tds)
print("---------------")
datas = []
for td in list_tds:
#print(td.text_content())
datas.append(td.text_content())
print(datas)
print("---------------")
print(np.array(datas).reshape(6,3)) #페이지처럼 2차원배열(6,3)로 변경
print("---------------")
print("number of row :",int(len(datas)/len(column_names)))
print("number of col :",len(column_names))
print("---------------")
arr = np.array(datas).reshape(int(len(datas)/len(column_names)),len(column_names))
print(arr)
print("---------------")
print(pd.DataFrame(arr,columns=column_names))
#21read_html_bs4 - 웹페이지 파싱 라이브러리
#from bs4 import BeautifulSoup
#from urllib.request import urlopen
#from urllib.parse import quote
<URL(동아일보) 응답 받기>
- url = "http://www.donga.com/news/search?query=python"
- str_text = urlopen(url).read().decode('utf-8') #코드 형태로 응답 수령
#print(dir(BeautifulSoup))
print("---------------")
url = "http://www.donga.com/news/search?query=python"
print("---url 접속-----")
httpResp = urlopen(url)
print(httpResp)#http.client.HTTPResponse
print("---응답 결과 코드 반환-----")
print(httpResp.getcode())#200,404,500
print("---응답내용 출력----")
str_text = httpResp.read().decode('utf-8')
#print(str_text)
<뉴스 별 링크 추출하기>
- soup = BeautifulSoup(str_text,features="lxml")
- rs = soup.find_all('p',{'class':'tit'})#p태그의 tit 속성만 추출 <p class="tit">
- 뉴스 기사별 url추출
for tit in rs:
print(tit.find('a')['href']) #<a href="https://www.donga.com/news/article/all/20...16982/1"
<뉴스 기사 내용 추출하기>
list_news = []
#뉴스 기사 url 파싱 및 한글 처리
for tit in rs:
link_url = tit.find('a')['href']
str_text = urlopen(link_url).read().decode('utf-8')
#httpResp = urlopen(link_url)
#str_text = httpResp.read().decode('utf-8')
soup = BeautifulSoup(str_text,features="lxml")
#print(soup)
#뉴스 본문 내용 찾기
article_txt = soup.find('div',{'class':'article_txt'}) #<div class='article_txt"
#print(type(article_txt))
#뉴스 내용이 있는 경우만, 리스트에 추가
if type(article_txt) != type(None):
print(article_txt.text)
list_news.append(article_txt.text)
print("---------------")
print(list_news)
#UTF-8 파싱에러 발생시 아래 코드로 변경
def test():
url = "https://finance.naver.com/item/coinfo.naver?code=005930"
print("---url 접속-----")
httpResp = urlopen(url)
print(httpResp)#http.client.HTTPResponse
print("---응답 결과 코드 반환-----")
print(httpResp.getcode())#200,404,500
print("---응답내용 출력----")
str_text = httpResp.read()
#print(str_text)
soup = BeautifulSoup(str_text,'html.parser',from_encoding='utf-8')
print(soup)
test() #웹 페이지 코드까지만 출력
--예문 코드 보기--
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
print("---------------")
from bs4 import BeautifulSoup
from urllib.request import urlopen
from urllib.parse import quote
#print(dir(BeautifulSoup))
print("---------------")
url = "http://www.donga.com/news/search?query=python"
print("---url 접속-----")
httpResp = urlopen(url)
print(httpResp)#http.client.HTTPResponse
print("---응답 결과 코드 반환-----")
print(httpResp.getcode())#200,404,500
print("---응답내용 출력----")
str_text = httpResp.read().decode('utf-8')
#print(str_text)
print("-----BeautifulSoup-----")
soup = BeautifulSoup(str_text,features="lxml")
#print(soup)
print("---------------")
#</p><p class="tit">
rs = soup.find_all('p',{'class':'tit'})#p태그의 tit 속성만 추출
print(type(rs)) #<class 'bs4.element.ResultSet'>
print(rs)
print("---------------")
#뉴스 기사별 url추출
#<a href="https://www.donga.com/news/article/all/20...16982/1"
for tit in rs:
print(tit.find('a')['href'])
print("---------------")
print("---------------")
#<a href="https://www.donga.com/news/article/all/20...16982/1"
list_news = []
for tit in rs:
link_url = tit.find('a')['href']
str_text = urlopen(link_url).read().decode('utf-8')
#httpResp = urlopen(link_url)
#str_text = httpResp.read().decode('utf-8')
soup = BeautifulSoup(str_text,features="lxml")
#<div class='article_txt"
#print(soup)
article_txt = soup.find('div',{'class':'article_txt'})
#print(type(article_txt))
if type(article_txt) != type(None):
print(article_txt.text)
list_news.append(article_txt.text)
print("---------------")
print(list_news)
print("---------------")
def test():
url = "https://finance.naver.com/item/coinfo.naver?code=005930"
print("---url 접속-----")
httpResp = urlopen(url)
print(httpResp)#http.client.HTTPResponse
print("---응답 결과 코드 반환-----")
print(httpResp.getcode())#200,404,500
print("---응답내용 출력----")
str_text = httpResp.read()
#print(str_text)
soup = BeautifulSoup(str_text,'html.parser',from_encoding='utf-8')
print(soup)
test() #웹 페이지 코드까지만 출력