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
Berikut ini adalah versi skrip python3 (diuji pada python3.5 di Ubuntu 17.10 ).
Cara Penggunaan:
- Untuk menggunakannya memasukkan kedua kode dalam file. Sebagai contoh file kode
script.py
dan file paket requirement.txt
.
- Lari
pip install -r requirement.txt
.
- Jalankan skrip sebagai contoh
python3 script.py pa4080
Ini menggunakan beberapa perpustakaan:
Hal-hal yang perlu diketahui untuk mengembangkan program lebih lanjut (selain dokumen paket yang diperlukan):
- pustaka python: asyncio, json dan urllib.parse
- penyeleksi css ( mdn web docs ), juga beberapa html. lihat juga cara menggunakan pemilih css di browser Anda seperti artikel ini
Bagaimana itu bekerja:
- Pertama saya membuat pengunduh html sederhana. Ini adalah versi modifikasi dari sampel yang diberikan pada aiohttp doc.
- Setelah itu membuat parser baris perintah sederhana yang menerima nama pengguna dan nama file keluaran.
- Buat parser untuk tautan utas dan artikel utama. Menggunakan pdb dan manipulasi url sederhana harus melakukan pekerjaan.
- Gabungkan fungsi dan letakkan artikel utama di json, sehingga program lain dapat memprosesnya nanti.
Ada ide sehingga bisa dikembangkan lebih lanjut
- Buat subperintah lain yang menerima tautan modul tanggal: itu dapat dilakukan dengan memisahkan metode untuk menguraikan modul tanggal ke fungsinya sendiri dan menggabungkannya dengan subperintah baru.
- Caching tautan modul tanggal: buat file cache json setelah mendapatkan tautan utas. jadi program tidak perlu menguraikan tautan lagi. atau bahkan hanya men-cache seluruh artikel utama utas meskipun tidak cocok
Ini bukan jawaban yang paling elegan, tapi saya pikir ini lebih baik daripada menggunakan jawaban bash.
- Ini menggunakan Python, yang berarti dapat digunakan lintas platform.
- Instalasi sederhana, semua paket yang diperlukan dapat diinstal menggunakan pip
- Ini dapat dikembangkan lebih lanjut, lebih mudah dibaca programnya, lebih mudah dikembangkan.
- Ia melakukan pekerjaan yang sama dengan skrip bash hanya selama 13 menit .
sudo apt install python3-bs4 python3-click python3-aiohttp python3-async
tetapi saya tidak dapat menemukan - dari mana paket ituasync_timeout
berasal?Untuk menyelesaikan tugas ini, saya telah membuat skrip bash sederhana berikutnya yang terutama menggunakan alat CLI
wget
.Script memiliki tiga fungsi:
Fungsi pertama
get_url_map()
penggunaanwget
sebagai--spider
(yang berarti bahwa itu hanya akan memeriksa bahwa halaman ada) dan akan membuat rekursif-r
URL$MAP_FILE
dari$TARGET_URL
dengan tingkat kedalaman-l2
. (Contoh lain dapat ditemukan di sini: Konversi Situs Web ke PDF ). Dalam kasus saat ini$MAP_FILE
berisi sekitar 20 000 URL.Fungsi kedua
filter_url_map()
akan menyederhanakan konten$MAP_FILE
. Dalam hal ini kita hanya perlu baris (URL) yang berisi stringarticle&sid
dan jumlahnya sekitar 3000. Lebih banyak ide dapat ditemukan di sini: Bagaimana menghapus kata-kata tertentu dari baris file teks?Fungsi ketiga
get_key_urls()
akan menggunakanwget -qO-
(sebagai perintahcurl
- contoh ) untuk menampilkan konten setiap URL dari$MAP_FILE
dan akan mencoba untuk menemukan salah satu$KEY_WORDS
di dalamnya. Jika ada yang$KEY_WORDS
ditemukan di dalam konten URL tertentu, URL itu akan disimpan dalam$OUT_FILE
.Selama proses kerja, output skrip terlihat seperti yang ditunjukkan pada gambar berikutnya. Diperlukan sekitar 63 menit untuk menyelesaikannya jika ada dua kata kunci dan 42 menit ketika hanya satu kata kunci yang dicari.
sumber
Saya membuat ulang skrip saya berdasarkan jawaban yang diberikan oleh @karel ini . Sekarang skrip menggunakan
lynx
alih-alihwget
. Hasilnya menjadi lebih cepat secara signifikan.Versi saat ini melakukan pekerjaan yang sama selama 15 menit ketika ada dua kata kunci yang dicari dan hanya 8 menit jika kita mencari hanya satu kata kunci. Itu lebih cepat daripada solusi Python yang disediakan oleh @dan .
Selain itu
lynx
memberikan penanganan karakter non latin yang lebih baik.sumber