เดŽเดฒเตเดฒเดพ เดนเดฌเดฑเตเด‚ เด’เดฐเต เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ

เด—เตเดกเต เด†เดซเตเดฑเตเดฑเตผเดจเต‚เตบ. เดŽเดดเตเดคเดฟเดฏเดฟเดŸเตเดŸเต 2 เดตเตผเดทเด‚ เด•เดดเดฟเดžเตเดžเต. เด…เดตเดธเดพเดจ เดฒเต‡เด–เดจเด‚ เดนเดฌเดฑเดฟเดจเต† เดชเดพเดดเตโ€Œเดธเดฟเด‚เด—เต เดšเต†เดฏเตเดฏเตเดจเตเดจเดคเดฟเดจเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต, เดšเดฟเดฒ เดชเต‹เดฏเดฟเดจเตเดฑเตเด•เตพ เดฎเดพเดฑเดฟ.

เดนเดฌเดฑเดฟเดจเตเดฑเต† เด’เดฐเต เดชเด•เตผเดชเตเดชเต เดฒเดญเดฟเด•เตเด•เดพเตป เดžเดพเตป เด†เด—เตเดฐเดนเดฟเดšเตเดšเดชเตเดชเต‹เตพ, เดฐเดšเดฏเดฟเดคเดพเด•เตเด•เดณเตเดŸเต† เดŽเดฒเตเดฒเดพ เด‰เดณเตเดณเดŸเด•เตเด•เดตเตเด‚ เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเดฒเต‡เด•เตเด•เต เดธเด‚เดฐเด•เตเดทเดฟเด•เตเด•เตเดจเตเดจ เด’เดฐเต เดชเดพเดดเตเดธเตผ เดŽเดดเตเดคเดพเตป เดžเดพเตป เดคเต€เดฐเตเดฎเดพเดจเดฟเดšเตเดšเต. เด‡เดคเต เดŽเด™เตเด™เดจเต† เดธเด‚เดญเดตเดฟเดšเตเดšเต, เดŽเดจเตเดคเต เดชเดฟเดถเด•เตเด•เตพ เดžเดพเตป เดจเต‡เดฐเดฟเดŸเตเดŸเต - เดจเดฟเด™เตเด™เตพเด•เตเด•เต เด•เดŸเตเดŸเดฟเดจเต เด•เต€เดดเดฟเตฝ เดตเดพเดฏเดฟเด•เตเด•เดพเด‚.

TL;DR - เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเต เดฒเดฟเด™เตเด•เต

เดชเดพเตผเดธเดฑเดฟเดจเตเดฑเต† เด†เดฆเตเดฏ เดชเดคเดฟเดชเตเดชเต. เด’เดฐเต เดคเตเดฐเต†เดกเต, เดจเดฟเดฐเดตเดงเดฟ เดชเตเดฐเดถเตเดจเด™เตเด™เตพ

เดคเตเดŸเด•เตเด•เดคเตเดคเดฟเตฝ, เดžเดพเตป เด’เดฐเต เดธเตเด•เตเดฐเดฟเดชเตเดฑเตเดฑเต เดชเตเดฐเต‹เดŸเตเดŸเต‹เดŸเตˆเดชเตเดชเต เดจเดฟเตผเดฎเตเดฎเดฟเด•เตเด•เดพเตป เดคเต€เดฐเตเดฎเดพเดจเดฟเดšเตเดšเต, เด…เดคเดฟเตฝ เดฒเต‡เด–เดจเด‚ เดกเต—เตบเดฒเต‹เดกเต เดšเต†เดฏเตเดฏเตเดฎเตเดชเต‹เตพ เดคเดจเตเดจเต† เดชเดพเดดเตโ€Œเดธเต เดšเต†เดฏเตเดฏเตเด•เดฏเตเด‚ เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ เดธเตเดฅเดพเดชเดฟเด•เตเด•เตเด•เดฏเตเด‚ เดšเต†เดฏเตเดฏเตเด‚. เดฐเดฃเตเดŸเตเดคเดตเดฃ เด†เดฒเต‹เดšเดฟเด•เตเด•เดพเดคเต†, เดžเดพเตป sqlite3 เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต, เด•เดพเดฐเดฃเด‚. เด‡เดคเดฟเดจเต เด…เดงเตเดตเดพเดจเด‚ เด•เตเดฑเดตเดพเดฏเดฟเดฐเตเดจเตเดจเต: เด’เดฐเต เดชเตเดฐเดพเดฆเต‡เดถเดฟเด• เดธเต†เตผเดตเตผ เด†เดตเดถเตเดฏเดฎเดฟเดฒเตเดฒ, เดธเตƒเดทเตเดŸเดฟเดšเตเดšเดคเดพเดฏเดฟ เด•เดพเดฃเดชเตเดชเต†เดŸเตเดŸเต-เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เดฟเดฏเดคเตเด‚ เด…เดคเตเดชเต‹เดฒเตเดณเตเดณเดตเดฏเตเด‚.

one_thread.py

from bs4 import BeautifulSoup
import sqlite3
import requests
from datetime import datetime

def main(min, max):
    conn = sqlite3.connect('habr.db')
    c = conn.cursor()
    c.execute('PRAGMA encoding = "UTF-8"')
    c.execute("CREATE TABLE IF NOT EXISTS habr(id INT, author VARCHAR(255), title VARCHAR(255), content  TEXT, tags TEXT)")

    start_time = datetime.now()
    c.execute("begin")
    for i in range(min, max):
        url = "https://m.habr.com/post/{}".format(i)
        try:
            r = requests.get(url)
        except:
            with open("req_errors.txt") as file:
                file.write(i)
            continue
        if(r.status_code != 200):
            print("{} - {}".format(i, r.status_code))
            continue

        html_doc = r.text
        soup = BeautifulSoup(html_doc, 'html.parser')

        try:
            author = soup.find(class_="tm-user-info__username").get_text()
            content = soup.find(id="post-content-body")
            content = str(content)
            title = soup.find(class_="tm-article-title__text").get_text()
            tags = soup.find(class_="tm-article__tags").get_text()
            tags = tags[5:]
        except:
            author,title,tags = "Error", "Error {}".format(r.status_code), "Error"
            content = "ะŸั€ะธ ะฟะฐั€ัะธะฝะณะต ัั‚ะพะน ัั‚ั€ะฐะฝะธั†ะต ะฟั€ะพะธะทะพัˆะปะฐ ะพัˆะธะฑะบะฐ."

        c.execute('INSERT INTO habr VALUES (?, ?, ?, ?, ?)', (i, author, title, content, tags))
        print(i)
    c.execute("commit")
    print(datetime.now() - start_time)

main(1, 490406)

เดŽเดฒเตเดฒเดพเด‚ เด•เตเดฒเดพเดธเดฟเด•เต เด†เดฃเต - เดžเด™เตเด™เตพ เดฌเตเดฏเต‚เดŸเตเดŸเดฟเดซเตเตพ เดธเต‚เดชเตเดชเต เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเดจเตเดจเต, เด…เดญเตเดฏเตผเดคเตเดฅเดจเด•เตพ, เด’เดฐเต เดฆเตเดฐเตเดค เดชเตเดฐเต‹เดŸเตเดŸเต‹เดŸเตˆเดชเตเดชเต เดคเดฏเตเดฏเดพเดฑเดพเดฃเต. เด…เดคเต เดตเต†เดฑเตเด‚โ€ฆ

  • เดชเต‡เดœเต เดกเต—เตบเดฒเต‹เดกเต เด’เดฐเต เดคเตเดฐเต†เดกเดฟเดฒเดพเดฃเต

  • เดจเดฟเด™เตเด™เตพ เดธเตเด•เตเดฐเดฟเดชเตเดฑเตเดฑเดฟเดจเตเดฑเต† เดจเดฟเตผเดตเตเดตเดนเดฃเด‚ เดคเดŸเดธเตเดธเดชเตเดชเต†เดŸเตเดคเตเดคเตเด•เดฏเดพเดฃเต†เด™เตเด•เดฟเตฝ, เดฎเตเดดเตเดตเตป เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเตเด‚ เดŽเดตเดฟเดŸเต†เดฏเตเด‚ เดชเต‹เด•เดฟเดฒเตเดฒ. เดŽเดฒเตเดฒเดพเดคเตเดคเดฟเดจเตเดฎเตเดชเดฐเดฟ, เดŽเดฒเตเดฒเดพ เดชเดพเดดเตเดธเดฟเด‚เด—เดฟเดจเตเด‚ เดถเต‡เดทเด‚ เดฎเดพเดคเตเดฐเดฎเดพเดฃเต เด•เดฎเตเดฎเดฟเดฑเตเดฑเต เดจเดŸเดคเตเดคเตเดจเตเดจเดคเต.
    เดคเต€เตผเดšเตเดšเดฏเดพเดฏเตเด‚, เด“เดฐเต‹ เด‰เตพเดชเตเดชเต†เดŸเตเดคเตเดคเดฒเดฟเดจเต เดถเต‡เดทเดตเตเด‚ เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ เดฎเดพเดฑเตเดฑเด™เตเด™เตพ เดตเดฐเตเดคเตเดคเดพเตป เด•เดดเดฟเดฏเตเด‚, เดŽเดจเตเดจเดพเตฝ เดธเตเด•เตเดฐเดฟเดชเตเดฑเตเดฑเต เดŽเด•เตเดธเดฟเด•เตเดฏเต‚เดทเตป เดธเดฎเดฏเด‚ เด—เดฃเตเดฏเดฎเดพเดฏเดฟ เดตเตผเดฆเตเดงเดฟเด•เตเด•เตเด‚.

  • เด†เดฆเตเดฏเดคเตเดคเต† 100 เดฒเต‡เด–เดจเด™เตเด™เตพ เดชเดพเดดเตโ€Œเดธเต เดšเต†เดฏเตเดฏเดพเตป เดŽเดจเดฟเด•เตเด•เต 000 เดฎเดฃเดฟเด•เตเด•เต‚เตผ เดŽเดŸเตเดคเตเดคเต.

เด…เดŸเตเดคเตเดคเดคเดพเดฏเดฟ เดžเดพเตป เด‰เดชเดฏเต‹เด•เตเดคเดพเดตเดฟเดจเตเดฑเต† เดฒเต‡เด–เดจเด‚ เด•เดฃเตเดŸเต†เดคเตเดคเตเดจเตเดจเต เดธเด‚เดฏเต‹เดœเดฟเดชเตเดชเดฟเดšเตเดšเต, เดˆ เดชเตเดฐเด•เตเดฐเดฟเดฏ เดตเต‡เด—เดคเตเดคเดฟเดฒเดพเด•เตเด•เดพเตป เดžเดพเตป เดตเดพเดฏเดฟเด•เตเด•เตเด•เดฏเตเด‚ เดšเดฟเดฒ เดฒเตˆเดซเต เดนเดพเด•เตเด•เตเด•เตพ เด•เดฃเตเดŸเต†เดคเตเดคเตเด•เดฏเตเด‚ เดšเต†เดฏเตเดคเต:

  • เดฎเตพเดŸเตเดŸเดฟเดคเตเดฐเต†เดกเดฟเด‚เด—เต เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเดจเตเดจเดคเต เดšเดฟเดฒ เดธเดฎเดฏเด™เตเด™เดณเดฟเตฝ เดกเต—เตบเดฒเต‹เดกเต เดตเต‡เด—เดคเตเดคเดฟเดฒเดพเด•เตเด•เตเดจเตเดจเต.
  • เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดนเดฌเดฑเดฟเดจเตเดฑเต† เดชเต‚เตผเดฃเตเดฃ เดชเดคเดฟเดชเตเดชเดฒเตเดฒ, เด…เดคเดฟเดจเตเดฑเต† เดฎเตŠเดฌเตˆเตฝ เดชเดคเดฟเดชเตเดชเต เดฒเดญเดฟเด•เตเด•เตเด‚.
    เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, เดกเต†เดธเตเด•เตเดŸเต‹เดชเตเดชเต เดชเดคเดฟเดชเตเดชเดฟเดฒเต† เด’เดฐเต เดธเด‚เดฏเต‹เดœเดฟเดค เดฒเต‡เด–เดจเดคเตเดคเดฟเดจเต 378 KB เดญเดพเดฐเดฎเตเดฃเตเดŸเต†เด™เตเด•เดฟเตฝ, เดฎเตŠเดฌเตˆเตฝ เดชเดคเดฟเดชเตเดชเดฟเตฝ เด…เดคเต เด‡เดคเดฟเดจเด•เด‚ 126 KB เด†เดฃเต.

เดฐเดฃเตเดŸเดพเด‚ เดชเดคเดฟเดชเตเดชเต. เดจเดฟเดฐเดตเดงเดฟ เดคเตเดฐเต†เดกเตเด•เตพ, เดนเดฌเดฑเดฟเตฝ เดจเดฟเดจเตเดจเตเดณเตเดณ เดคเดพเตฝเด•เตเด•เดพเดฒเดฟเด• เดจเดฟเดฐเต‹เดงเดจเด‚

เดชเตˆเดคเตเดคเดฃเดฟเดฒเต† เดฎเตพเดŸเตเดŸเดฟเดคเตเดฐเต†เดกเดฟเด‚เด—เต เดŽเดจเตเดจ เดตเดฟเดทเดฏเดคเตเดคเดฟเตฝ เดžเดพเตป เด‡เดจเตเดฑเตผเดจเต†เดฑเตเดฑเต เดชเดฐเดฟเดถเต‹เดงเดฟเดšเตเดšเดชเตเดชเต‹เตพ, multiprocessing.dummy เด‰เดณเตเดณ เดเดฑเตเดฑเดตเตเด‚ เดฒเดณเดฟเดคเดฎเดพเดฏ เด“เดชเตเดทเตป เดžเดพเตป เดคเดฟเดฐเดžเตเดžเต†เดŸเตเดคเตเดคเต, เดฎเตพเดŸเตเดŸเดฟเดคเตเดฐเต†เดกเดฟเด‚เด—เดฟเดจเตŠเดชเตเดชเด‚ เดชเตเดฐเดถเตเดจเด™เตเด™เตพ เดชเตเดฐเดคเตเดฏเด•เตเดทเดชเตเดชเต†เดŸเตเดจเตเดจเดคเต เดžเดพเตป เดถเตเดฐเดฆเตเดงเดฟเดšเตเดšเต.

SQLite3 เด’เดจเตเดจเดฟเดฒเดงเดฟเด•เด‚ เดคเตเดฐเต†เดกเตเด•เดณเดฟเตฝ เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เดพเตป เด†เด—เตเดฐเดนเดฟเด•เตเด•เตเดจเตเดจเดฟเดฒเตเดฒ.
เดจเดฟเดถเตเดšเดฟเดค check_same_thread=False, เดŽเดจเตเดจเดพเตฝ เดˆ เดชเดฟเดถเด•เต เดฎเดพเดคเตเดฐเดฎเดฒเตเดฒ, เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเดฒเต‡เด•เตเด•เต เดคเดฟเดฐเตเด•เดพเตป เดถเตเดฐเดฎเดฟเด•เตเด•เตเดฎเตเดชเต‹เตพ, เดŽเดจเดฟเด•เตเด•เต เดชเดฐเดฟเดนเดฐเดฟเด•เตเด•เดพเตป เด•เดดเดฟเดฏเดพเดคเตเดค เดชเดฟเดถเด•เตเด•เตพ เดšเดฟเดฒเดชเตเดชเต‹เตพ เดธเด‚เดญเดตเดฟเด•เตเด•เตเดจเตเดจเต.

เด…เดคเดฟเดจเดพเตฝ, เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเดฒเต‡เด•เตเด•เต เดจเต‡เดฐเดฟเดŸเตเดŸเต เดฒเต‡เด–เดจเด™เตเด™เตพ เดšเต‡เตผเด•เตเด•เตเดจเตเดจเดคเต เด‰เดชเต‡เด•เตเดทเดฟเด•เตเด•เดพเตป เดžเดพเตป เดคเต€เดฐเตเดฎเดพเดจเดฟเด•เตเด•เตเดจเตเดจเต, เด’เดชเตเดชเด‚ เดธเด‚เดฏเต‹เดœเดฟเดค เดชเดฐเดฟเดนเดพเดฐเด‚ เด“เตผเดคเตเดคเตเด•เตŠเดฃเตเดŸเต, เดซเดฏเดฒเตเด•เตพ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเตป เดžเดพเตป เดคเต€เดฐเตเดฎเดพเดจเดฟเด•เตเด•เตเดจเตเดจเต, เด•เดพเดฐเดฃเด‚ เด’เดฐเต เดซเดฏเดฒเดฟเดฒเต‡เด•เตเด•เต เดฎเตพเดŸเตเดŸเดฟ-เดคเตเดฐเต†เดกเต เดŽเดดเตเดคเตเดจเตเดจเดคเดฟเตฝ เดชเตเดฐเดถเตโ€Œเดจเด™เตเด™เดณเตŠเดจเตเดจเตเดฎเดฟเดฒเตเดฒ.

เดฎเต‚เดจเตเดจเดฟเตฝ เด•เต‚เดŸเตเดคเตฝ เดคเตเดฐเต†เดกเตเด•เตพ เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเดคเดฟเดจเต เดนเดฌเตเตผ เดจเดฟเดฐเต‹เดงเดฟเด•เตเด•เดพเตป เดคเตเดŸเด™เตเด™เตเดจเตเดจเต.
เดชเตเดฐเดคเตเดฏเต‡เด•เดฟเดšเตเดšเตเด‚ เดนเดฌเดฑเดฟเดฒเต‡เด•เตเด•เต เด•เดŸเด•เตเด•เดพเดจเตเดณเตเดณ เดคเต€เด•เตเดทเตเดฃเดฎเดพเดฏ เดถเตเดฐเดฎเด™เตเด™เตพ เดเดคเดพเดจเตเด‚ เดฎเดฃเดฟเด•เตเด•เต‚เดฑเตเด•เตพเด•เตเด•เตเดณเตเดณ เดเดชเดฟ เดจเดฟเดฐเต‹เดงเดจเดคเตเดคเดฟเตฝ เด…เดตเดธเดพเดจเดฟเด•เตเด•เตเด‚. เด…เดคเดฟเดจเดพเตฝ เดจเดฟเด™เตเด™เตพ 3 เดคเตเดฐเต†เดกเตเด•เตพ เดฎเดพเดคเตเดฐเดฎเต‡ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเดตเต‚, เดชเด•เตเดทเต‡ เด‡เดคเต เด‡เดคเดฟเดจเด•เด‚ เดจเดฒเตเดฒเดคเดพเดฃเต, เด•เดพเดฐเดฃเด‚ 100-เดฒเดงเดฟเด•เด‚ เดฒเต‡เด–เดจเด™เตเด™เตพ เด†เดตเตผเดคเตเดคเดฟเด•เตเด•เดพเดจเตเดณเตเดณ เดธเดฎเดฏเด‚ 26-เตฝ เดจเดฟเดจเตเดจเต 12 เดธเต†เด•เตเด•เตปเดกเดพเดฏเดฟ เด•เตเดฑเดžเตเดžเต.

เดˆ เดชเดคเดฟเดชเตเดชเต เด…เดธเตเดฅเดฟเดฐเดฎเดพเดฃเต†เดจเตเดจเดคเต เดถเตเดฐเดฆเตเดงเดฟเด•เตเด•เต‡เดฃเตเดŸเดคเดพเดฃเต, เด•เต‚เดŸเดพเดคเต† เดกเต—เตบเดฒเต‹เดกเตเด•เตพ เด‡เดŸเดฏเตเด•เตเด•เดฟเดŸเต† เดงเดพเดฐเดพเดณเด‚ เดฒเต‡เด–เดจเด™เตเด™เดณเดฟเตฝ เดตเต€เดดเตเดจเตเดจเต.

async_v1.py

from bs4 import BeautifulSoup
import requests
import os, sys
import json
from multiprocessing.dummy import Pool as ThreadPool
from datetime import datetime
import logging

def worker(i):
    currentFile = "files\{}.json".format(i)

    if os.path.isfile(currentFile):
        logging.info("{} - File exists".format(i))
        return 1

    url = "https://m.habr.com/post/{}".format(i)

    try: r = requests.get(url)
    except:
        with open("req_errors.txt") as file:
            file.write(i)
        return 2

    # ะ—ะฐะฟะธััŒ ะทะฐะฑะปะพะบะธั€ะพะฒะฐะฝะฝั‹ั… ะทะฐะฟั€ะพัะพะฒ ะฝะฐ ัะตั€ะฒะตั€
    if (r.status_code == 503):
        with open("Error503.txt", "a") as write_file:
            write_file.write(str(i) + "n")
            logging.warning('{} / 503 Error'.format(i))

    # ะ•ัะปะธ ะฟะพัั‚ะฐ ะฝะต ััƒั‰ะตัั‚ะฒัƒะตั‚ ะธะปะธ ะพะฝ ะฑั‹ะป ัะบั€ั‹ั‚
    if (r.status_code != 200):
        logging.info("{} / {} Code".format(i, r.status_code))
        return r.status_code

    html_doc = r.text
    soup = BeautifulSoup(html_doc, 'html5lib')

    try:
        author = soup.find(class_="tm-user-info__username").get_text()

        timestamp = soup.find(class_='tm-user-meta__date')
        timestamp = timestamp['title']

        content = soup.find(id="post-content-body")
        content = str(content)
        title = soup.find(class_="tm-article-title__text").get_text()
        tags = soup.find(class_="tm-article__tags").get_text()
        tags = tags[5:]

        # ะœะตั‚ะบะฐ, ั‡ั‚ะพ ะฟะพัั‚ ัะฒะปัะตั‚ัั ะฟะตั€ะตะฒะพะดะพะผ ะธะปะธ ั‚ัƒั‚ะพั€ะธะฐะปะพะผ.
        tm_tag = soup.find(class_="tm-tags tm-tags_post").get_text()

        rating = soup.find(class_="tm-votes-score").get_text()
    except:
        author = title = tags = timestamp = tm_tag = rating = "Error" 
        content = "ะŸั€ะธ ะฟะฐั€ัะธะฝะณะต ัั‚ะพะน ัั‚ั€ะฐะฝะธั†ะต ะฟั€ะพะธะทะพัˆะปะฐ ะพัˆะธะฑะบะฐ."
        logging.warning("Error parsing - {}".format(i))
        with open("Errors.txt", "a") as write_file:
            write_file.write(str(i) + "n")

    # ะ—ะฐะฟะธัั‹ะฒะฐะตะผ ัั‚ะฐั‚ัŒัŽ ะฒ json
    try:
        article = [i, timestamp, author, title, content, tm_tag, rating, tags]
        with open(currentFile, "w") as write_file:
            json.dump(article, write_file)
    except:
        print(i)
        raise

if __name__ == '__main__':
    if len(sys.argv) < 3:
        print("ะะตะพะฑั…ะพะดะธะผั‹ ะฟะฐั€ะฐะผะตั‚ั€ั‹ min ะธ max. ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต: async_v1.py 1 100")
        sys.exit(1)
    min = int(sys.argv[1])
    max = int(sys.argv[2])

    # ะ•ัะปะธ ะฟะพั‚ะพะบะพะฒ >3
    # ั‚ะพ ั…ะฐะฑั€ ะฑะฐะฝะธั‚ ipัˆะฝะธะบ ะฝะฐ ะฒั€ะตะผั
    pool = ThreadPool(3)

    # ะžั‚ัั‡ะตั‚ ะฒั€ะตะผะตะฝะธ, ะทะฐะฟัƒัะบ ะฟะพั‚ะพะบะพะฒ
    start_time = datetime.now()
    results = pool.map(worker, range(min, max))

    # ะŸะพัะปะต ะทะฐะบั€ั‹ั‚ะธั ะฒัะตั… ะฟะพั‚ะพะบะพะฒ ะฟะตั‡ะฐั‚ะฐะตะผ ะฒั€ะตะผั
    pool.close()
    pool.join()
    print(datetime.now() - start_time)

เดฎเต‚เดจเตเดจเดพเด‚ เดชเดคเดฟเดชเตเดชเต. เดซเตˆเดจเตฝ

เดฐเดฃเตเดŸเดพเดฎเดคเตเดคเต† เดชเดคเดฟเดชเตเดชเต เดกเต€เดฌเด—เตเด—เต เดšเต†เดฏเตเดฏเตเดฎเตเดชเต‹เตพ, เดธเตˆเดฑเตเดฑเดฟเดจเตเดฑเต† เดฎเตŠเดฌเตˆเตฝ เดชเดคเดฟเดชเตเดชเต เด†เด•เตโ€Œเดธเดธเต เดšเต†เดฏเตเดฏเตเดจเตเดจ เด’เดฐเต เดŽเดชเดฟเด เดนเดฌเตโ€Œเดฑเดฟเดจเต เดชเต†เดŸเตเดŸเต†เดจเตเดจเต เด‰เดฃเตเดŸเต†เดจเตเดจเต เดžเดพเตป เด•เดฃเตเดŸเต†เดคเตเดคเดฟ. เด‡เดคเต เดฎเตŠเดฌเตˆเตฝ เดชเดคเดฟเดชเตเดชเดฟเดจเต‡เด•เตเด•เดพเตพ เดตเต‡เด—เดคเตเดคเดฟเตฝ เดฒเต‹เดกเตเดšเต†เดฏเตเดฏเตเดจเตเดจเต, เด•เดพเดฐเดฃเด‚ เด‡เดคเต json เดฎเดพเดคเตเดฐเดฎเดพเดฃเต, เด…เดคเต เดชเดพเดดเตโ€Œเดธเต เดšเต†เดฏเตเดฏเต‡เดฃเตเดŸเดคเดฟเดฒเตเดฒ. เด…เดตเดธเดพเดจเด‚, เดŽเดจเตเดฑเต† เดธเตเด•เตเดฐเดฟเดชเตเดฑเตเดฑเต เดตเต€เดฃเตเดŸเตเด‚ เดŽเดดเตเดคเดพเตป เดžเดพเตป เดคเต€เดฐเตเดฎเดพเดจเดฟเดšเตเดšเต.

เด…เดคเดฟเดจเดพเตฝ, เด•เดฃเตเดŸเต†เดคเตเดคเดฟ เดˆ เดฒเดฟเด™เตเด•เต API, เดจเดฟเด™เตเด™เตพเด•เตเด•เต เด‡เดคเต เดชเดพเดดเตโ€Œเดธเต เดšเต†เดฏเตเดฏเดพเตป เดคเตเดŸเด™เตเด™เดพเด‚.

async_v2.py

import requests
import os, sys
import json
from multiprocessing.dummy import Pool as ThreadPool
from datetime import datetime
import logging

def worker(i):
    currentFile = "files\{}.json".format(i)

    if os.path.isfile(currentFile):
        logging.info("{} - File exists".format(i))
        return 1

    url = "https://m.habr.com/kek/v1/articles/{}/?fl=ru%2Cen&hl=ru".format(i)

    try:
        r = requests.get(url)
        if r.status_code == 503:
            logging.critical("503 Error")
            return 503
    except:
        with open("req_errors.txt") as file:
            file.write(i)
        return 2

    data = json.loads(r.text)

    if data['success']:
        article = data['data']['article']

        id = article['id']
        is_tutorial = article['is_tutorial']
        time_published = article['time_published']
        comments_count = article['comments_count']
        lang = article['lang']
        tags_string = article['tags_string']
        title = article['title']
        content = article['text_html']
        reading_count = article['reading_count']
        author = article['author']['login']
        score = article['voting']['score']

        data = (id, is_tutorial, time_published, title, content, comments_count, lang, tags_string, reading_count, author, score)
        with open(currentFile, "w") as write_file:
            json.dump(data, write_file)

if __name__ == '__main__':
    if len(sys.argv) < 3:
        print("ะะตะพะฑั…ะพะดะธะผั‹ ะฟะฐั€ะฐะผะตั‚ั€ั‹ min ะธ max. ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต: asyc.py 1 100")
        sys.exit(1)
    min = int(sys.argv[1])
    max = int(sys.argv[2])

    # ะ•ัะปะธ ะฟะพั‚ะพะบะพะฒ >3
    # ั‚ะพ ั…ะฐะฑั€ ะฑะฐะฝะธั‚ ipัˆะฝะธะบ ะฝะฐ ะฒั€ะตะผั
    pool = ThreadPool(3)

    # ะžั‚ัั‡ะตั‚ ะฒั€ะตะผะตะฝะธ, ะทะฐะฟัƒัะบ ะฟะพั‚ะพะบะพะฒ
    start_time = datetime.now()
    results = pool.map(worker, range(min, max))

    # ะŸะพัะปะต ะทะฐะบั€ั‹ั‚ะธั ะฒัะตั… ะฟะพั‚ะพะบะพะฒ ะฟะตั‡ะฐั‚ะฐะตะผ ะฒั€ะตะผั
    pool.close()
    pool.join()
    print(datetime.now() - start_time)

เดฒเต‡เด–เดจเดตเตเดฎเดพเดฏเตเด‚ เด…เดคเต เดŽเดดเตเดคเดฟเดฏ เดฐเดšเดฏเดฟเดคเดพเดตเตเดฎเดพเดฏเตเด‚ เดฌเดจเตเดงเดชเตเดชเต†เดŸเตเดŸ เดซเต€เตฝเดกเตเด•เตพ เด‡เดคเดฟเตฝ เด…เดŸเด™เตเด™เดฟเดฏเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเต.

API.png

เดŽเดฒเตเดฒเดพ เดนเดฌเดฑเตเด‚ เด’เดฐเต เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ

เด“เดฐเต‹ เดฒเต‡เด–เดจเดคเตเดคเดฟเดจเตเดฑเต†เดฏเตเด‚ เดชเต‚เตผเดฃเตเดฃเดฎเดพเดฏ json เดžเดพเตป เด‰เดชเต‡เด•เตเดทเดฟเดšเตเดšเดฟเดฒเตเดฒ, เดชเด•เตเดทเต‡ เดŽเดจเดฟเด•เตเด•เต เด†เดตเดถเตเดฏเดฎเดพเดฏ เดซเต€เตฝเดกเตเด•เตพ เดฎเดพเดคเตเดฐเด‚ เดธเด‚เดฐเด•เตเดทเดฟเดšเตเดšเต:

  • id
  • เดŸเตเดฏเต‚เดŸเตเดŸเต‹เดฑเดฟเดฏเตฝ เด†เดฃเต
  • เดธเดฎเดฏเด‚_เดชเตเดฐเดธเดฟเดฆเตเดงเต€เด•เดฐเดฟเดšเตเดšเดคเต
  • เดคเดฒเด•เตเด•เต†เดŸเตเดŸเต
  • เด‰เดณเตเดณเดŸเด•เตเด•เด‚
  • เด…เดญเดฟเดชเตเดฐเดพเดฏเด™เตเด™เดณเตเดŸเต†_เดŽเดฃเตเดฃเด‚
  • เดฒเต‡เด–เดจเด‚ เดŽเดดเตเดคเดฟเดฏ เดญเดพเดทเดฏเดพเดฃเต lang. เด‡เดคเตเดตเดฐเต† en, ru เดŽเดจเตเดจเดฟเดต เดฎเดพเดคเตเดฐเดฎเต‡ เด‰เดณเตเดณเต‚.
  • tags_string - เดชเต‹เดธเตเดฑเตเดฑเดฟเตฝ เดจเดฟเดจเตเดจเตเดณเตเดณ เดŽเดฒเตเดฒเดพ เดŸเดพเด—เตเด•เดณเตเด‚
  • เดตเดพเดฏเดจ_เดŽเดฃเตเดฃเด‚
  • เดฐเดšเดฏเดฟเดคเดพเดตเต
  • เดธเตเด•เต‹เตผ - เดฒเต‡เด–เดจ เดฑเต‡เดฑเตเดฑเดฟเด‚เด—เต.

เด…เด™เตเด™เดจเต†, API เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต, เดžเดพเตป เดธเตเด•เตเดฐเดฟเดชเตเดฑเตเดฑเต เดŽเด•เตเดธเดฟเด•เตเดฏเต‚เดทเตป เดธเดฎเดฏเด‚ 8 url-เดจเต 100 เดธเต†เด•เตเด•เตปเดกเดพเดฏเดฟ เด•เตเดฑเดšเตเดšเต.

เดžเด™เตเด™เตพเด•เตเด•เต เด†เดตเดถเตเดฏเดฎเดพเดฏ เดกเดพเดฑเตเดฑ เดกเต—เตบเดฒเต‹เดกเต เดšเต†เดฏเตเดค เดถเต‡เดทเด‚, เดžเด™เตเด™เตพ เด…เดคเต เดชเตเดฐเต‹เดธเดธเตเดธเต เดšเต†เดฏเตเดฏเตเด•เดฏเตเด‚ เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ เดจเตฝเด•เตเด•เดฏเตเด‚ เดตเต‡เดฃเด‚. เด‡เดคเดฟเดฒเตเด‚ เดŽเดจเดฟเด•เตเด•เต เดชเตเดฐเดถเตโ€Œเดจเด™เตเด™เดณเตŠเดจเตเดจเตเด‚ เด‰เดฃเตเดŸเดพเดฏเดฟเดฐเตเดจเตเดจเดฟเดฒเตเดฒ:

parser.py

import json
import sqlite3
import logging
from datetime import datetime

def parser(min, max):
    conn = sqlite3.connect('habr.db')
    c = conn.cursor()
    c.execute('PRAGMA encoding = "UTF-8"')
    c.execute('PRAGMA synchronous = 0') # ะžั‚ะบะปัŽั‡ะฐะตะผ ะฟะพะดั‚ะฒะตั€ะถะดะตะฝะธะต ะทะฐะฟะธัะธ, ั‚ะฐะบ ัะบะพั€ะพัั‚ัŒ ัƒะฒะตะปะธั‡ะธะฒะฐะตั‚ัั ะฒ ั€ะฐะทั‹.
    c.execute("CREATE TABLE IF NOT EXISTS articles(id INTEGER, time_published TEXT, author TEXT, title TEXT, content TEXT, 
    lang TEXT, comments_count INTEGER, reading_count INTEGER, score INTEGER, is_tutorial INTEGER, tags_string TEXT)")
    try:
        for i in range(min, max):
            try:
                filename = "files\{}.json".format(i)
                f = open(filename)
                data = json.load(f)

                (id, is_tutorial, time_published, title, content, comments_count, lang,
                 tags_string, reading_count, author, score) = data

                # ะ ะฐะดะธ ะปัƒั‡ัˆะตะน ั‡ะธั‚ะฐะตะผะพัั‚ะธ ะฑะฐะทั‹ ะผะพะถะฝะพ ะฟั€ะตะฝะตะฑั€ะตั‡ัŒ ั‡ะธั‚ะฐะตะผะพัั‚ัŒัŽ ะบะพะดะฐ. ะ˜ะปะธ ะฝะตั‚?
                # ะ•ัะปะธ ะฒะฐะผ ั‚ะฐะบ ะบะฐะถะตั‚ัั, ะผะพะถะฝะพ ะฟั€ะพัั‚ะพ ะทะฐะผะตะฝะธั‚ัŒ ะบะพั€ั‚ะตะถ ะฐั€ะณัƒะผะตะฝั‚ะพะผ data. ะ ะตัˆะฐั‚ัŒ ะฒะฐะผ.

                c.execute('INSERT INTO articles VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', (id, time_published, author,
                                                                                        title, content, lang,
                                                                                        comments_count, reading_count,
                                                                                        score, is_tutorial,
                                                                                        tags_string))
                f.close()

            except IOError:
                logging.info('FileNotExists')
                continue

    finally:
        conn.commit()

start_time = datetime.now()
parser(490000, 490918)
print(datetime.now() - start_time)

เดธเตเดฅเดฟเดคเดฟเดตเดฟเดตเดฐเด•เตเด•เดฃเด•เตเด•เตเด•เตพ

เดถเดฐเดฟ, เดชเดฐเดฎเตเดชเดฐเดพเด—เดคเดฎเดพเดฏเดฟ, เด’เดŸเตเดตเดฟเตฝ, เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดกเดพเดฑเตเดฑเดฏเดฟเตฝ เดจเดฟเดจเตเดจเต เดšเดฟเดฒ เดธเตเดฅเดฟเดคเดฟเดตเดฟเดตเดฐเด•เตเด•เดฃเด•เตเด•เตเด•เตพ เดตเต‡เตผเดคเดฟเดฐเดฟเดšเตเดšเต†เดŸเตเด•เตเด•เดพเตป เด•เดดเดฟเดฏเตเด‚:

  • เดชเตเดฐเดคเต€เด•เตเดทเดฟเดšเตเดš 490 เดกเต—เตบเดฒเต‹เดกเตเด•เดณเดฟเตฝ 406 เดฒเต‡เด–เดจเด™เตเด™เตพ เดฎเดพเดคเตเดฐเดฎเดพเดฃเต เดกเต—เตบเดฒเต‹เดกเต เดšเต†เดฏเตเดฏเดชเตเดชเต†เดŸเตเดŸเดคเต. เดนเดฌเตเดฐเต†เดฏเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเตเดณเตเดณ เดฒเต‡เด–เดจเด™เตเด™เดณเดฟเตฝ เดชเด•เตเดคเดฟเดฏเดฟเดฒเต‡เดฑเต†เดฏเตเด‚ (228) เดฎเดฑเดฏเตเด•เตเด•เตเด•เดฏเต‹ เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เตเด•เดฏเต‹ เดšเต†เดฏเตเดคเต.
  • เดเด•เดฆเต‡เดถเด‚ เด…เดฐ เดฆเดถเดฒเด•เตเดทเด‚ เดฒเต‡เด–เดจเด™เตเด™เตพ เด…เดŸเด™เตเด™เตเดจเตเดจ เดฎเตเดดเตเดตเตป เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเดจเตเดฑเต†เดฏเตเด‚ เดญเดพเดฐเด‚ 2.95 GB เด†เดฃเต. เด•เด‚เดชเตเดฐเดธเต เดšเต†เดฏเตเดค เดฐเต‚เดชเดคเตเดคเดฟเตฝ - 495 MB.
  • เดฎเตŠเดคเตเดคเดคเตเดคเดฟเตฝ, 37804 เด†เดณเตเด•เตพ เดนเดฌเตเดฐเต†เดฏเตเดŸเต† เดฐเดšเดฏเดฟเดคเดพเด•เตเด•เดณเดพเดฃเต. เดˆ เดธเตเดฅเดฟเดคเดฟเดตเดฟเดตเดฐเด•เตเด•เดฃเด•เตเด•เตเด•เตพ เดคเดคเตเดธเดฎเดฏ เดชเต‹เดธเตเดฑเตเดฑเตเด•เดณเดฟเตฝ เดจเดฟเดจเตเดจเตเดณเตเดณเดคเดพเดฃเต†เดจเตเดจเต เดžเดพเตป เดจเดฟเด™เตเด™เดณเต† เด“เตผเดฎเตเดฎเดฟเดชเตเดชเดฟเด•เตเด•เตเดจเตเดจเต.
  • เดนเดฌเตเดฐเต†เดฏเดฟเดฒเต† เดเดฑเตเดฑเดตเตเด‚ เด‰เตฝเดชเตเดชเดพเดฆเดจเด•เตเดทเดฎเดฎเดพเดฏ เดฐเดšเดฏเดฟเดคเดพเดตเต - เด…เดฒเดฟเดธเตผ - 8774 เดฒเต‡เด–เดจเด™เตเด™เตพ.
  • เดเดฑเตเดฑเดตเตเด‚ เดฎเดฟเด•เดšเตเดš เดฑเต‡เดฑเตเดฑเตเดšเต†เดฏเตเดค เดฒเต‡เด–เดจเด‚ - 1448 เดชเตเดฒเดธเต
  • เดเดฑเตเดฑเดตเตเด‚ เด•เต‚เดŸเตเดคเตฝ เดตเดพเดฏเดฟเด•เตเด•เดชเตเดชเต†เดŸเตเดŸ เดฒเต‡เด–เดจเด‚ โ€“ 1660841 เด•เดพเดดเตเดšเด•เตพ
  • เดเดฑเตเดฑเดตเตเด‚ เด•เต‚เดŸเตเดคเตฝ เดšเตผเดšเตเดš เดšเต†เดฏเตเดฏเดชเตเดชเต†เดŸเตเดŸ เดฒเต‡เด–เดจเด‚ - 2444 เด…เดญเดฟเดชเตเดฐเดพเดฏเด™เตเด™เตพ

เดจเดจเตเดจเดพเดฏเดฟ, เดฌเดฒเดฟ เดฐเต‚เดชเดคเตเดคเดฟเตฝเดฎเดฟเด•เดšเตเดš 15 เดŽเดดเตเดคเตเดคเตเด•เดพเตผเดŽเดฒเตเดฒเดพ เดนเดฌเดฑเตเด‚ เด’เดฐเต เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ
เดฑเต‡เดฑเตเดฑเดฟเด‚เด—เต เดชเตเดฐเด•เดพเดฐเด‚ เดฎเดฟเด•เดšเตเดš 15เดŽเดฒเตเดฒเดพ เดนเดฌเดฑเตเด‚ เด’เดฐเต เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ
เดฎเดฟเด•เดšเตเดš 15 เดตเดพเดฏเดฟเด•เตเด•เตเด•เดŽเดฒเตเดฒเดพ เดนเดฌเดฑเตเด‚ เด’เดฐเต เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ
เดฎเดฟเด•เดšเตเดš 15 เดšเตผเดšเตเดš เดšเต†เดฏเตเดคเตเดŽเดฒเตเดฒเดพ เดนเดฌเดฑเตเด‚ เด’เดฐเต เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ

เด…เดตเดฒเด‚เดฌเด‚: www.habr.com

เด’เดฐเต เด…เดญเดฟเดชเตเดฐเดพเดฏเด‚ เดšเต‡เตผเด•เตเด•เตเด•