Source code for openpibo.collect

"""
인터넷에서 **위키 검색 정보, 날씨 정보, 뉴스 정보** 를 가져올 수 있습니다.

Class:
:obj:`~openpibo.collect.Wikipedia`
:obj:`~openpibo.collect.Weather`
:obj:`~openpibo.collect.News`
"""

from urllib.parse import quote
from bs4 import BeautifulSoup
import requests

[문서]class Wikipedia: """ Functions: :meth:`~openpibo.collect.Wikipedia.search` :meth:`~openpibo.collect.Wikipedia.search_s` 위키백과에서 단어를 검색합니다. example:: from openpibo.collect import Wikipedia wiki = Wikipedia() # 아래의 모든 예제 이전에 위 코드를 먼저 사용합니다. """
[문서] def search(self, search_text: str): """ 위키백과에서 ``search_text`` 를 검색합니다. example:: result = wiki.search('강아지') :param str search_text: 위키백과에서의 검색어 :returns: 내용을 dictionary 배열 형태로 반환합니다. 대부분의 경우 '0'번 항목에 개요를 표시하고, 검색된 내용이 없을 경우 None을 반환합니다. example:: ['0':{ 'title': '명칭', 'content': "한국어 ‘강아지’는 ‘개’에 어린 짐승을 뜻하는 ‘아지’가 붙은 말이다..." }, ... ] or None """ _chapters = {'0':{'title':'개요', 'content':[]}} encode_text = quote(search_text) url = f'https://ko.wikipedia.org/wiki/{encode_text}' resp = requests.get(url, headers={'User-Agent' : 'Mozilla/5.0'}) soup = BeautifulSoup(resp.content, 'html.parser') total_content = soup.find('div', {'class': 'mw-parser-output'}) if not total_content: return None # chapter_idx = '3.1', chapter_list = [3, 1] chapter_idx, chapter_list = '0', [0] parent_num = 0 for content in total_content: tag = content.name if tag == None: continue elif tag[0] == 'h': new_parent_num = int(tag[1]) - 2 if new_parent_num <= parent_num: chapter_list = chapter_list[:new_parent_num+1] chapter_list[-1] += 1 else: chapter_list.append(1) chapter_idx = '.'.join(map(str, chapter_list)) _chapters[chapter_idx] = {} _chapters[chapter_idx]['title'] = content.text.split('[')[0] _chapters[chapter_idx]['content'] = [] elif tag == 'p': _chapters[chapter_idx]['content'].append(content.text) elif tag == 'ul': _chapters[chapter_idx]['content'].append(content.text) return _chapters
[문서] def search_s(self, search_text: str): """ 위키백과에서 ``search_text`` 를 검색합니다. (block 전용) example:: result = wiki.search_s('강아지') :param str search_text: 위키백과에서의 검색어 :returns: search 함수의 반환 값의 content만 추출한 리스트를 반환합니다. 대부분의 경우 '0'번 항목에 개요를 표시하고, 검색된 내용이 없을 경우 None을 반환합니다. example:: [ "한국어 ‘강아지’는 ‘개’에 어린 짐승을 뜻하는 ‘아지’가 붙은 말이다...", ... ] or None """ res = self.search(search_text) return [item.strip().replace('\n', '') for _, v in res.items() if len(v['content']) > 0 for item in v['content'] if item != '\n']
[문서]class Weather: """ Functions: :meth:`~openpibo.collect.Weather.search` :meth:`~openpibo.collect.Weather.search_s` 종합 예보와 오늘/내일/모레의 날씨 정보를 검색합니다. example:: from openpibo.collect import Weather weather = Weather() # 아래의 모든 예제 이전에 위 코드를 먼저 사용합니다. """ region_list = { '전국': 108, '서울': 109, '인천': 109, '경기': 109, '부산': 159, '울산': 159, '경남': 159, '대구': 143, '경북': 143, '광주': 156, '전남': 156, '전북': 146, '대전': 133, '세종': 133, '충남': 133, '충북': 131, '강원': 105, '제주': 184, } """ 날씨 정보를 검색할 수 있는 지역입니다. """
[문서] def search(self, search_region:str='전국'): """ 해당 지역(```search_region```)의 날씨 정보(종합예보, 오늘/내일/모레 날씨)를 가져옵니다. example:: result = weather.search('서울') :param str search_region: 검색 가능한 지역 (default: 전국) 검색할 수 있는 지역은 다음과 같습니다:: '전국', '서울', '인천', '경기', '부산', '울산', '경남', '대구', '경북', '광주', '전남', '전북', '대전', '세종', '충남', '충북', '강원', '제주' :returns: 종합예보와 오늘/내일/모레의 날씨 및 최저/최고기온을 반환합니다. example:: { 'forecast': '내일 경기남부 가끔 비, 내일까지 바람 약간 강, 낮과 밤의 기온차 큼' 'today': { 'weather': '전국 대체로 흐림', 'minimum_temp': '15.3 ~ 21.6', 'highst_temp': '23.1 ~ 27.6' } 'tomorrow': { 'weather': '전국 대체로 흐림', 'minimum_temp': '15.3 ~ 21.6', 'highst_temp': '23.1 ~ 27.6' } 'after_tomorrow': { 'weather': '전국 대체로 흐림', 'minimum_temp': '15.3 ~ 21.6', 'highst_temp': '23.1 ~ 27.6' } } or None """ region = Weather.region_list.get(search_region) if region == None: raise Exception(f'"{search_region}" not support') _forecast = '' _today = {} _tomorrow = {} _after_tomorrow = {} url = f'https://www.weather.go.kr/w/weather/forecast/short-term.do?stnId={region}' resp = requests.get(url, headers={'User-Agent' : 'Mozilla/5.0'}) soup = BeautifulSoup(resp.content, 'html.parser') forecasts = soup.find('div', {'class': 'cmp-view-content'}).text forecasts = forecasts.split('□')[1].split('○') for forecast in map(str.strip, forecasts): split_point = forecast.index(')') date = forecast[:split_point+1] desc = forecast[split_point+2:] if '종합' in date: _forecast = desc if '오늘' in date: _today['weather'] = desc if '내일' in date or '~' in date: _tomorrow['weather'] = desc if '모레' in date: _after_tomorrow['weather'] = desc temp_table = soup.find('tbody') all_temps = list(map(lambda x: x.text, temp_table.select('td')[:10])) _today['minimum_temp'], _tomorrow['minimum_temp'], _after_tomorrow['minimum_temp'] = all_temps[2:5] _today['highst_temp'], _tomorrow['highst_temp'], _after_tomorrow['highst_temp'] = all_temps[7:10] return {'forecast':_forecast, 'today':_today, 'tomorrow':_tomorrow, 'after_tomorrow':_after_tomorrow}
[문서] def search_s(self, search_region:str='전국', search_type: str='forecast', search_item: str = 'weather'): """ 해당 지역(```search_region```)의 날씨 정보(종합예보, 오늘/내일/모레 날씨)를 가져옵니다. example:: result = weather.search_s('서울') :param str search_region: 검색 가능한 지역 (default: 전국) 검색할 수 있는 지역은 다음과 같습니다:: '전국', '서울', '인천', '경기', '부산', '울산', '경남', '대구', '경북', '광주', '전남', '전북', '대전', '세종', '충남', '충북', '강원', '제주' :param str search_type: 검색할 내용 (default: forecast) 검색할 내용은 다음과 같습니다:: 'forecast', 'today', 'tomorrow', 'after_tomorrow' :param str search_item: 검색할 내용 (default: weather) 검색할 내용은 다음과 같습니다:: 'weather', 'minimum_temp', 'highst_temp' search_type이 forecast일 경우, search_item은 무시합니다. :returns: 파라미터에 따라, 종합예보 혹은 오늘/내일/모레의 날씨, 최저기온, 최고기온을 반환합니다. example:: { 'forecast': '내일 경기남부 가끔 비, 내일까지 바람 약간 강, 낮과 밤의 기온차 큼' 'today': { 'weather': '전국 대체로 흐림', 'minimum_temp': '15.3 ~ 21.6', 'highst_temp': '23.1 ~ 27.6' } 'tomorrow': { 'weather': '전국 대체로 흐림', 'minimum_temp': '15.3 ~ 21.6', 'highst_temp': '23.1 ~ 27.6' } 'after_tomorrow': { 'weather': '전국 대체로 흐림', 'minimum_temp': '15.3 ~ 21.6', 'highst_temp': '23.1 ~ 27.6' } } or None """ res = self.search(search_region) if search_type == 'forecast': return res['forecast'].strip().replace('\n', ' ') else: # search_type ('today'|'tomorrow'|'after_tomorrow') if search_item == 'minimum_temp': return res[search_type][search_item].split(' ~ ')[0] elif search_item == 'highst_temp': return res[search_type][search_item].split(' ~ ')[1] else: # weather return res[search_type][search_item].strip().replace('\n', ' ')
[문서]class News: """ Functions: :meth:`~openpibo.collect.News.search` :meth:`~openpibo.collect.News.search_s` JTBC 뉴스 RSS 서비스를 사용해 뉴스 자료를 가져옵니다. example:: from openpibo.collect import News news = News() # 아래의 모든 예제 이전에 위 코드를 먼저 사용합니다. """ topic_list = { '속보': 'newsflash', '정치': 'politics', '경제': 'economy', '사회': 'society', '국제': 'international', '문화': 'culture', '연예': 'entertainment', '스포츠': 'sports', '풀영상': 'fullvideo', '뉴스랭킹': 'newsrank', '뉴스룸': 'newsroom', '아침&': 'morningand', '썰전 라이브': 'ssulzunlive', '정치부회의': 'politicaldesk', } """ 뉴스 정보를 검색할 수 있는 주제입니다. """
[문서] def search(self, search_topic:str = '뉴스랭킹'): """ 해당 주제(```search_topic```)에 맞는 뉴스를 가져옵니다. example:: result = news.search('속보') :param str search_topic: 검색 가능한 뉴스 주제 (default: 뉴스랭킹) 검색할 수 있는 주제는 다음과 같습니다:: '속보', '정치', '경제', '사회', '국제', '문화', '연예', '스포츠', '풀영상', '뉴스랭킹', '뉴스룸', '아침&', '썰전 라이브', '정치부회의' :returns: title, link, description, pubDate 요소가 있는 dictionary 배열입니다. example:: [ { 'title': '또 소방차 막은 불법주차, 이번엔 가차없이 밀어버렸다', 'link': 'https://news.jtbc.joins.com/article/article.aspx?...', 'description': '2019년 4월 소방당국의 불법주정차 강경대응 훈련 모습..., 'pubDate': '2021.09.03' }, ] or None """ topic = News.topic_list.get(search_topic) if topic == None: raise Exception(f'"{search_topic}" not support') _articles = [] url = f'https://fs.jtbc.joins.com//RSS/{topic}.xml' res = requests.get(url, headers={'User-Agent' : 'Mozilla/5.0'}) soup = BeautifulSoup(res.content, 'xml') items = soup.findAll('item') for item in items: _articles.append({ 'title':item.find('title').text, 'link':item.find('link').text, 'description':item.find('description').text, 'pubDate':item.find('pubDate').text }) return _articles
[문서] def search_s(self, search_topic:str = '뉴스랭킹', search_type:str = "title"): """ 해당 주제(```search_topic```)에 맞는 뉴스를 가져옵니다. example:: result = news.search_s('속보') :param str search_topic: 검색 가능한 뉴스 주제 (default: 뉴스랭킹) 검색할 수 있는 주제는 다음과 같습니다:: '속보', '정치', '경제', '사회', '국제', '문화', '연예', '스포츠', '풀영상', '뉴스랭킹', '뉴스룸', '아침&', '썰전 라이브', '정치부회의' :param str search_type: 검색할 내용 (default: title) 검색할 내용은 다음과 같습니다:: 'title', 'link', 'description' :returns: title, link, description 중 선택한 요소의 리스트 example:: [ '또 소방차 막은 불법주차, 이번엔 가차없이 밀어버렸다', ... ] or None """ res = self.search(search_topic) return [v[search_type] for v in res if '다시보기' not in v[search_type]]
if __name__ == "__main__": wiki = Wikipedia() weather = Weather() news = News() print('wiki:', wiki.search('로봇')) print('weather:', weather.search('서울')) print('news:', news.search('속보'))