Python

[Python] 판다스(pandas)_9. 웹 데이터 추출(read_xml, read_html, BeautifulSoup)

걍작 2022. 4. 17. 00:05

 

#정리

**트리(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() #웹 페이지 코드까지만 출력