[python]BeautifulSoup을 이용한 xml 파싱 및 txt 파일 중복 확인 후 리스트 저장

티스토리 rss를 살펴보면  rss/channel 안에 title(블로그명), link(블로그링크)가 있고 각각의 블로그 제목과 링크들이 들어있는 item이 반복됨을 알 수 있다.

blist =['https://letsplaycoding.tistory.com/rss']
asyncio.run(telegram_send([텔레그램봇아이디],"[xml 수집 시작 by 인포 메이크]"))

while True:
    for blog in blist :
        time.sleep(0.1)
        crawl_blog(blog)
    time.sleep(300)

여러 개의 xml 주소를 담을 수 있도록 배열을 선언하고 한 개의 블로그 주소를 넣어주었다.

반복문을 만들고 블로그 주소를 매개변수로 전달받는 crawl_blog라는 메소드를 만들었다.

time.sleep을 이용하면 해당시간동안 메소드를 일시정지 시킬 수 있다. 1초 단위, 300은 300초.

 

 

파이썬 requests 라이브러리를 이용해 전달받은 블로그주소를 호출한다.

호출에 성공하면 BeautifulSoup을 이용해 파싱을 해준다.

parser의 형식은  html.parser, xml, lxml, htm5lib 등이 있는데 속도가 빠르고 구문을 분석하기 좋은  lxml을 선택했다.

 

makedirs를 이용한 폴더 생성

def createFolder(directory):
    try:
        if not os.path.exists(directory):
            os.makedirs(directory, 0o666)
            p = open(directory+"/list.txt", 'w')
            p.close()
    except OSError:
        sys.exit('"' + directory + '" 폴더 만들기 실패')

channel = soup.find('title').text

soup.find를 이용해 title을 변수로 담아 폴더를 생성한다.

폴더를 생성할때에는 list.txt라는 파일도 함께 생성시켜 준다.

 

파일 읽기 후 중복되지 않는 블로그 주소 파일에 추가

def filesave(directory,lst):
    f = open(directory+"/list.txt", 'r')
    lines = f.readlines()
    for line in lines:
        print("파일 읽기 : "+line)
        lst.append(line.strip())
    f.close   
    return lst

lst = []
blist = filesave(save_folder+channel, lst)

배열을 하나 만들고 중복확인을 위해 해당폴더의 list.txt 파일을 읽어 배열에 담아둔다.

 

bsItem = soup.select('item',limit=5)     
for item in list(bsItem):
title_str = item.title.text
link_str = item.link.text

if link_str in blist :
    print("파일 내용 중복 O")  
else :
    print("파일 내용 중복 X")
    p = open(save_folder+channel+"/list.txt", 'a')
    p.write(link_str.strip()+"\r\n")
    p.close()

 

soup.select('item',limit=5)를 이용해 item묶음을 리스트로 받는다.

이때 limit를 통해 몇 개의 item을 가지고 올지 선택할 수 있다.

item 리스트는 포문을 돌려 타이틀과 링크 주소를 각각 변수에 담는다.

파일에서 읽은 리스트와 링크 주소를 비교해 파일안에 링크가 존재하지 않는다면 링크주소를 추가한다.

 

txt 파일을 확인해 보면 링크 주소가 한줄 한줄 입력이 돼있는 것을 확인할 수 있다.

 

텔레그램 푸시

async def telegram_send(chat_id, text):
        print("telegram send : "+text)
        bot = telegram.Bot(token='텔레그램봇토큰')
        await bot.send_message(chat_id,text)

편의를 위해 새로운 글이 발견되면 텔레그램 알람으로 푸시하게 했다.

텔레그램 봇의 경우 예전에는 bot.send_message만 쓰면 가볍게 사용이 가능했는데..

버전이 올라가면서 RuntimeWarning: coroutine 'Bot.send_message' was never awaited 이런 에러가 났다.

이는 asyncio를 설치하고 비동기식으로 함수를 호출하면 해결된다.

 

이렇게 해서 간단하게 xml을 읽어서 txt 파일에 저장하고 새로운 글일 경우 텔레그램 알람이 오게 만들어 보았다.