script.py
:
#!/usr/bin/python3
from urllib.parse import urljoin
import json
import bs4
import click
import aiohttp
import asyncio
import async_timeout
BASE_URL = 'http://e-bane.net'
async def fetch(session, url):
try:
with async_timeout.timeout(20):
async with session.get(url) as response:
return await response.text()
except asyncio.TimeoutError as e:
print('[{}]{}'.format('timeout error', url))
with async_timeout.timeout(20):
async with session.get(url) as response:
return await response.text()
async def get_result(user):
target_url = 'http://e-bane.net/modules.php?name=Stories_Archive'
res = []
async with aiohttp.ClientSession() as session:
html = await fetch(session, target_url)
html_soup = bs4.BeautifulSoup(html, 'html.parser')
date_module_links = parse_date_module_links(html_soup)
for dm_link in date_module_links:
html = await fetch(session, dm_link)
html_soup = bs4.BeautifulSoup(html, 'html.parser')
thread_links = parse_thread_links(html_soup)
print('[{}]{}'.format(len(thread_links), dm_link))
for t_link in thread_links:
thread_html = await fetch(session, t_link)
t_html_soup = bs4.BeautifulSoup(thread_html, 'html.parser')
if is_article_match(t_html_soup, user):
print('[v]{}'.format(t_link))
# to get main article, uncomment below code
# res.append(get_main_article(t_html_soup))
# code below is used to get thread link
res.append(t_link)
else:
print('[x]{}'.format(t_link))
return res
def parse_date_module_links(page):
a_tags = page.select('ul li a')
hrefs = a_tags = [x.get('href') for x in a_tags]
return [urljoin(BASE_URL, x) for x in hrefs]
def parse_thread_links(page):
a_tags = page.select('table table tr td > a')
hrefs = a_tags = [x.get('href') for x in a_tags]
# filter href with 'file=article'
valid_hrefs = [x for x in hrefs if 'file=article' in x]
return [urljoin(BASE_URL, x) for x in valid_hrefs]
def is_article_match(page, user):
main_article = get_main_article(page)
return main_article.text.startswith(user)
def get_main_article(page):
td_tags = page.select('table table td.row1')
td_tag = td_tags[4]
return td_tag
@click.command()
@click.argument('user')
@click.option('--output-filename', default='out.json', help='Output filename.')
def main(user, output_filename):
loop = asyncio.get_event_loop()
res = loop.run_until_complete(get_result(user))
# if you want to return main article, convert html soup into text
# text_res = [x.text for x in res]
# else just put res on text_res
text_res = res
with open(output_filename, 'w') as f:
json.dump(text_res, f)
if __name__ == '__main__':
main()
requirement.txt
:
aiohttp>=2.3.7
beautifulsoup4>=4.6.0
click>=6.7
다음은 python3 버전의 스크립트입니다 (Ubuntu 17.10의 python3.5에서 테스트 ).
사용하는 방법:
- 그것을 사용하려면 두 코드를 모두 파일에 넣으십시오. 예를 들어 코드 파일은
script.py
이고 패키지 파일은 requirement.txt
입니다.
- 를 실행하십시오
pip install -r requirement.txt
.
- 스크립트를 예제로 실행
python3 script.py pa4080
여러 라이브러리를 사용합니다.
프로그램을 추가로 개발하기 위해 알아야 할 사항 (필수 패키지 문서 제외) :
- 파이썬 라이브러리 : asyncio, json 및 urllib.parse
- CSS 선택기 ( mdn web docs ) 및 일부 HTML. 이 기사 와 같은 브라우저에서 CSS 선택기를 사용하는 방법도 참조 하십시오.
작동 방식 :
- 먼저 간단한 html 다운로더를 만듭니다. aiohttp doc에 제공된 샘플에서 수정 된 버전입니다.
- 그 후에 사용자 이름과 출력 파일 이름을 허용하는 간단한 명령 줄 파서를 만듭니다.
- 스레드 링크 및 기본 아티클에 대한 구문 분석기를 작성하십시오. pdb와 간단한 URL 조작을 사용하면 문제가 해결됩니다.
- 함수를 결합하고 주요 기사를 json에 넣으면 나중에 다른 프로그램에서 처리 할 수 있습니다.
더 발전시킬 수있는 아이디어
- 날짜 모듈 링크를 승인하는 다른 부속 명령을 작성하십시오. 메소드를 분리하여 날짜 모듈을 자체 기능으로 구문 분석하고이를 새로운 부속 명령과 결합하여 수행 할 수 있습니다.
- 날짜 모듈 링크 캐싱 : 스레드 링크를 얻은 후 캐시 json 파일을 작성하십시오. 따라서 프로그램은 링크를 다시 구문 분석 할 필요가 없습니다. 또는 전체 스레드 기본 기사가 일치하지 않더라도 전체 캐시
이것은 가장 우아한 대답은 아니지만 bash 답변을 사용하는 것보다 낫다고 생각합니다.
- 파이썬을 사용하므로 크로스 플랫폼에서 사용할 수 있습니다.
- 간단한 설치, 모든 필수 패키지는 pip를 사용하여 설치할 수 있습니다
- 프로그램을 더 잘 읽을 수 있고 더 쉽게 개발할 수 있습니다.
- 13 분 동안 만 bash 스크립트 와 동일한 작업을 수행합니다 .
sudo apt install python3-bs4 python3-click python3-aiohttp python3-async
. 그러나 어떤 패키지async_timeout
에서 나온 패키지를 찾을 수 없습니까?