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
Đây là phiên bản python3 của tập lệnh (được thử nghiệm trên python3.5 trên Ubuntu 17.10 ).
Cách sử dụng:
- Để sử dụng nó đặt cả hai mã trong các tập tin. Ví dụ tập tin mã là
script.py
và tập tin gói là requirement.txt
.
- Chạy đi
pip install -r requirement.txt
.
- Chạy script như ví dụ
python3 script.py pa4080
Nó sử dụng một số thư viện:
Những điều cần biết để phát triển chương trình hơn nữa (ngoài tài liệu của gói yêu cầu):
- thư viện python: asyncio, json và urllib.parse
- bộ chọn css ( tài liệu web mdn ), cũng có một số html. xem thêm cách sử dụng bộ chọn css trên trình duyệt của bạn, chẳng hạn như bài viết này
Làm thế nào nó hoạt động:
- Đầu tiên tôi tạo một trình tải xuống html đơn giản. Nó là phiên bản sửa đổi từ mẫu được đưa ra trên tài liệu aiohttp.
- Sau đó, tạo trình phân tích cú pháp dòng lệnh đơn giản chấp nhận tên người dùng và tên tệp đầu ra.
- Tạo một trình phân tích cú pháp cho các liên kết chủ đề và bài viết chính. Sử dụng pdb và thao tác url đơn giản sẽ thực hiện công việc.
- Kết hợp chức năng và đặt bài viết chính trên json, để chương trình khác có thể xử lý nó sau.
Một số ý tưởng để nó có thể được phát triển thêm
- Tạo một tiểu ban khác chấp nhận liên kết mô-đun ngày: có thể được thực hiện bằng cách tách phương thức để phân tích mô-đun ngày thành chức năng của chính nó và kết hợp nó với tiểu ban mới.
- Bộ nhớ đệm liên kết mô-đun ngày: tạo tập tin bộ nhớ cache sau khi nhận được liên kết chủ đề. vì vậy chương trình không phải phân tích lại liên kết. hoặc thậm chí chỉ lưu trữ toàn bộ bài viết chính của chủ đề ngay cả khi nó không khớp
Đây không phải là câu trả lời tao nhã nhất, nhưng tôi nghĩ nó tốt hơn là sử dụng câu trả lời bash.
- Nó sử dụng Python, có nghĩa là nó có thể được sử dụng đa nền tảng.
- Cài đặt đơn giản, tất cả các gói cần thiết có thể được cài đặt bằng pip
- Nó có thể được phát triển hơn nữa, chương trình dễ đọc hơn, dễ dàng phát triển hơn.
- Nó thực hiện công việc tương tự như tập lệnh bash chỉ trong 13 phút .
sudo apt install python3-bs4 python3-click python3-aiohttp python3-async
nhưng tôi không thể tìm thấy - góiasync_timeout
đến từ đâu?