廃止された(廃止された)文献フォーラムe-bane.net内で自分の記事を見つけたいと思います。一部のフォーラムモジュールが無効になっており、著者による記事のリストを取得できません。また、このサイトは、Google、Yndexなどの検索エンジンによってインデックスに登録されていません。
私のすべての記事を見つける唯一の方法は、サイトのアーカイブページを開くことです(図1)。次に、特定の年と月を選択する必要があります。例: 2013年1月(図1)。次に、各記事(図2)を調べて、最初に私のニックネームが書かれているかどうかを確認する必要があります– pa4080 (図3)。しかし、数千の記事があります。
次のようないくつかのトピックを読みましたが、どのソリューションも私のニーズに適合していません。
- Ubuntu用のWebスパイダー
- LinuxシステムでWebスパイダーを作成する方法
- サイトからURLのリストを取得する
私は自分の解決策を投稿します。しかし、私にとっては興味深いものです。
このタスクを解決するためのよりエレガントな方法はありますか?
承認された回答:
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
いくつかのライブラリを使用します:
- 引数パーサーをクリックしてください
- htmlパーサー用のbeautifulsoup
- aiohttpforhtmlダウンローダー
プログラムをさらに発展させるために知っておくべきこと(必要なパッケージのドキュメント以外):
- Pythonライブラリ:asyncio、json、urllib.parse
- cssセレクター(mdn web docs)、またいくつかのhtml。この記事など、ブラウザでcssセレクタを使用する方法も参照してください
仕組み:
- 最初に、単純なhtmlダウンローダーを作成します。これは、aiohttpドキュメントに記載されているサンプルから変更されたバージョンです。
- その後、ユーザー名と出力ファイル名を受け入れる簡単なコマンドラインパーサーを作成します。
- スレッドリンクとメイン記事のパーサーを作成します。 pdbと単純なURL操作を使用することでうまくいくはずです。
- 関数を組み合わせてメインの記事をjsonに配置し、他のプログラムが後で処理できるようにします。
さらに発展させるためのアイデア
- 日付モジュールリンクを受け入れる別のサブコマンドを作成します。これは、日付モジュールを解析するメソッドを独自の関数に分離し、新しいサブコマンドと組み合わせると実行できます。
- 日付モジュールリンクのキャッシュ:スレッドリンクを取得した後、キャッシュjsonファイルを作成します。そのため、プログラムはリンクを再度解析する必要はありません。または、スレッドのメイン記事全体が一致しない場合でもキャッシュするだけです
これは最も洗練された答えではありませんが、bashの答えを使用するよりも優れていると思います。
- Pythonを使用しているため、クロスプラットフォームで使用できます。
- 簡単なインストール。必要なすべてのパッケージはpipを使用してインストールできます
- さらに開発することができ、プログラムを読みやすくし、開発を容易にすることができます。
- bashスクリプトと同じ仕事を13分間だけ行います 。