'데이터분석/R & Python'에 해당되는 글 2건

  1. 2017.03.09 주식 회복 탄력성 지수 구하는 모듈 ver 1.0
  2. 2016.08.11 특정 주제 목록 캡쳐그림/목록 가져오기 (Python)

from bs4 import BeautifulSoup
import requests
import urllib
import datetime, time
from prettytable import PrettyTable
## resilience 주식의 회복 탄력성을 계산해주는 로직
class Resilience :
# 1~ 513 페이지를 네비게이션하면서 1996년도에서 오늘까지의 일일 종가 데이터를 가져온다.
domainUrl = 'http://finance.naver.com/item/sise_day.nhn?code='
pageUrl = '&page='
threshold_DroppedPersent = 5
threshold_MaxDayToCountupRecoveryTime = 1000
def main(self, code):
prices = Resilience.getPricesFromWeb(self, code)
dropPrices = Resilience.getDropBadlyList(self,prices)
dropPrices = Resilience.calculateDaysToBeRecovered(self,prices,dropPrices)
Resilience.printRecoveryReport(self,dropPrices)
newsList = Resilience.getNewsList(self,code)
dropPrices = Resilience.appendRelatedNewsOnDroppedDay(self,dropPrices,newsList)
Resilience.printResultWithNews(self,dropPrices)
def getPricesFromWeb(self, code):
# last page 구하는 로직 구현
last_page_index = 50
list = []
for page in range(1, last_page_index):
url = Resilience.domainUrl + code + str(Resilience.pageUrl) + str(page)
source_code = requests.get(url, timeout=None)
soup = BeautifulSoup(source_code.text, 'lxml')
tableSoup = soup.find('table', attrs={'class', 'type2'})
trSoup = tableSoup.find_all('tr')
i = 0
rowcount = 0;
for tr in trSoup:
i = i + 1
if i > 2 and i < 16 and i <= len(tr):
if i == 8 or i == 9 or i == 10:
continue
j = 0
dic = {}
for td in tr:
j = j + 1
if j == 2:
date_str = str(td.span.text)
date_str = date_str.replace(".", "")
dic['date'] = datetime.date(int(date_str[0:4]), int(date_str[4:6]), int(date_str[6:8]))
if j == 4:
price = str(td.span.text)
dic['price'] = int(price.replace(',', ''))
if j == 6:
change = str(td.span.text).strip()
if change != '0':
if td.img['src'].endswith('ico_up.gif') or td.img['src'].endswith('ico_up2.gif'):
dic['change'] = int(change.replace(',', ''))
else:
dic['change'] = -1 * int(change.replace(',', ''))
else:
dic['change'] = 0
list.append(dic)
return list
def getDropBadlyList(self, list):
# 하루 등락률이 10프로 하락하는 지점을 찾는다. 하락을 했다면 그날의 시가를 가지고 향후 언제 그 가격을 넘어서는지를 찾을 것이다.
# 전날 종가를 기준으로 등락률을 매기는게 맞는데 그냥 당일 종가와 등락 가격을 가지고 퍼센티지를 계산함.
drop_badly_list = []
for day in list :
#print(day['date'] + " : " + str(day['price']) + " : " + str(day['change']))
percent = ( day['price'] + day['change'] ) / day['price'] * 100 - 100
#print(day['date'] + " : " + str(percent))
if percent < -1 * Resilience.threshold_DroppedPersent :
drop_badly_list.append(day)
# 그래서 우선 list를 filter해서 가지고 있고 그 시가를 가지고 있는 list를 만들 것이다. 그리고 이 filtered_list를 가지고 다시 원래의 list
return drop_badly_list
# 우선 특정 % 이상 떨어진 일자들을 얻고 각각 일자에 대해 전날 종가 가격으로의 회복 기간이 얼마 소요되었는지 하고 그것에 대한 평균도 구하도록 한다.
# threshold 한계값 정해서 이 값을 넘을 경우는 실제 계산에서 배제를 하도록 한다. : 추가 기능
def calculateDaysToBeRecovered(self, list, drop_badly_list):
# 날짜 오름차순으로 변경
list.reverse()
recovery = []
for drop_day in drop_badly_list:
change = drop_day['change']
yesterdayPrice = drop_day['price']
d = drop_day['date']
counting = 0
isCounting = False
element = {}
for day in list:
if day['date'] == d:
isCounting = True
yesterdayPrice -= change
theDay = d
if isCounting:
if yesterdayPrice < day['price']:
break
else:
counting = counting + 1
# print(day['date'],day['price'])
element['theDay'] = theDay
element['counting'] = counting
element['yesterdayPrice'] = yesterdayPrice
recovery.append(element)
return recovery
def printRecoveryReport(self, recovery):
t = PrettyTable(['5% 이상 떨어진 일자','회복하는데 걸린 일수', '회복해야하는 주가'])
for ele in recovery:
t.add_row([ele['theDay'], ele['counting'], ele['yesterdayPrice']])
print(t)
# for ele in recovery :
# print('----------------------------')
# print('5% 이상 떨어진 일자 : ', ele['theDay'])
# print('회복하는데 걸린 일수 : ', ele['counting'])
# print('회복해야하는 주가 : ', ele['yesterdayPrice'])
sum = 0
for ele in recovery :
sum = sum + ele['counting']
print('The average of days to recover is ' , sum/len(recovery))
def getNewsList(self, code):
# 그다음 이시기에 어떤 뉴스가 있었는지를 찾기 위해서 네이버 증권의 뉴스데이터를 이용한다.
news_domain = 'http://finance.naver.com/item/news_news.nhn?code='+ code
news_domain_with_pageNo = 'http://finance.naver.com/item/news_news.nhn?code=' + code + '&page='
source_code = requests.get(news_domain, timeout=None)
soup = BeautifulSoup(source_code.text, 'lxml')
tableSoup = soup.find('table', attrs={'class', 'Nnavi'} )
td = tableSoup.find('td', attrs={'class','pgRR'}).a['href']
last_page_index = int(td[td.index('page=') + 5:])
last_page_index = 300
news_list = []
# for page in range(1,last_page_index) :
for page in range(600, 900):
url = news_domain_with_pageNo + str(page)
source_code = requests.get(url, timeout=None)
soup = BeautifulSoup(source_code.text, 'lxml')
newsTabelSoup = soup.find('table', attrs={'class', 'type2'})
trSoup = newsTabelSoup.find_all('tr')
i = 0
rowcount = 0;
for tr in trSoup:
i = i + 1
if i > 2 and i < 16:
if i == 8 or i == 9:
continue
j = 0
dic = {}
for td in tr:
j = j + 1
if j == 2:
strDate = str(td.span.text)
# print(strDate)
yyyy = int(strDate[0:4])
mm = int(strDate[5:7])
dd = int(strDate[8:10])
# 나중에 시간이 오후 3시 30분 이후에 있는건 제외를 하자. 다음날 영향 변수
hh = int(strDate[11:13])
minutes = int(strDate[14:16])
# dic['date'] = str(td.span.text)
dic['date'] = datetime.date(int(yyyy), int(mm), int(dd))
if j == 4:
dic['title'] = td.a.text
if j == 6:
dic['publish'] = td.text
news_list.append(dic)
return news_list
def appendRelatedNewsOnDroppedDay(self, recovery, news_list):
for recv in recovery:
d = recv['theDay']
news_list2 = []
for news in news_list:
if news.get('date') == d:
# print(news['title'])
news_list2.append(news['title'])
recv['news_list'] = news_list2
return recovery
def printResultWithNews(self, recovery):
import pprint
pprint.pprint(recovery)
#print(recovery)
# t = PrettyTable(['Date','Original Price', 'DaysToBeRecovered', 'NewsList'])
#
# for recv in recovery:
# t.add_row([recv['theDay'], recv['yesterdayPrice'], recv['counting'], recv['news_list']])
#
# print(t)
view raw Resilience.py hosted with ❤ by GitHub

Posted by 억사마
데이터분석/R & Python2016. 8. 11. 18:03

파이선 컨을 앞두고 파이선 재미난 코드 snippet 을 보다가 하나 따라해봄. (출처)

주피터에 있는걸 복붙. 사전에 webkit2png  설치가 필요하며 그리고 실행하는 경로에 images라는 폴더 생성을 해야한다.



import requests # http 
import bs4  # beautiful soup
import re # reqular expression
import subprocess # capture screen
import json  #json util
import os # os util 사용하기 위
In [39]:
# Requests
BASE_URL_SDS = "http://search.daum.net/search?nil_suggest=btn&w=news&DA=SBC&cluster=y&q=%EC%82%BC%EC%84%B1sds"
data = requests.get(BASE_URL_SDS)

# row개수 확인
data = bs4.BeautifulSoup(data.text)
# 아래는 reqular expression을 이용하여 totalCount를 가져오는 예제
match = re.search("totalCount: [0-9]+", data.text)
# total Count를 가져오는 부분이며 두번째 인덱스에 숫자가들어있것지
total_count = int(match.group(0).split("totalCount: ")[1])
/Users/jouk/Workspace/python/test/images
In [50]:
# 총 페이지 개수 (페이지당 10개)
pages = total_count / 10 + 1
article_data = [] #아티클 보관할 배열 생성

# 오호라 이 문법은 정말 신기하구먼 자바랑 좀 다른건가 for in 하고 비슷하긴한데 range라는게 있구먼..
for page in range(1, pages+1):
    TARGET_URL = BASE_URL_SDS + "&p=" + str(page)
    data = requests.get(TARGET_URL)
    data = bs4.BeautifulSoup(data.text)
    articles = data.findAll("div", attrs={'class': 'cont_inner'})

    for article in articles:
        title_and_link = article.findAll("a")[0]
        title = title_and_link.text.encode('utf-8')
        link = title_and_link["href"]

        date_and_media = str(article.findAll("span", attrs={'class': 'date'})[0])
        date = date_and_media.split("\n")[1]
        media = date_and_media.split("\n")[2].split("</span> ")[1]

        article_data.append(
            {
                "title": title,
                "link": link,
                "date": date,
                "media": media,
            }
        )
        
        # 아래를 실행하기 위해서는 http://www.paulhammond.org/webkit2png/ 에서 우선 webkit2png가 필요!!
        # ScreenShot
        subprocess.call([
            "webkit2png",
            "-F",   # only create fullsize screenshot
            "--filename=temporary",
            "--dir=" + os.path.join(os.getcwd(), "images"),
            link
        ])
        # Rename Screenshot
        # webkit2png --filename=FILENAME 옵션을 사용하면 한글깨짐 문제 발생
        for filename in os.listdir("./images/"):
            if filename.startswith("temporary"):
                os.rename(
                    os.path.join(os.getcwd(), "images", filename),
                    os.path.join(os.getcwd(), "images",
                                "Screenshot_" + date + "_" + media + "_" + title.replace(" ", "_") + ".png")
                )

# Result as JSON
# 단, ensure_ascii 옵션으로 UTF-8 ( 한글로 보이도록 ) 출력한다.
with open('result.json', 'w') as outfile:
    json.dump(article_data, outfile, ensure_ascii=False)        





Posted by 억사마