เชเช• เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชฌเชงเชพ Habr

เชถเซเชญ เชฌเชชเซ‹เชฐ. เช† เชฒเช–เชพเชฏเชพเชจเซ‡ 2 เชตเชฐเซเชท เชฅเชˆ เช—เชฏเชพ เช›เซ‡. เช›เซ‡เชฒเซเชฒเซ‹ เชฒเซ‡เช– Habr เชจเชพ เชชเชฆเชšเซเช›เซ‡เชฆเชจ เชตเชฟเชถเซ‡, เช…เชจเซ‡ เช•เซ‡เชŸเชฒเชพเช• เชฎเซเชฆเซเชฆเชพ เชฌเชฆเชฒเชพเชฏเชพ เช›เซ‡.

เชœเซเชฏเชพเชฐเซ‡ เชนเซเช‚ Habr เชจเซ€ เชจเช•เชฒ เชฎเซ‡เชณเชตเชตเชพ เชฎเชพเช‚เช—เชคเซ‹ เชนเชคเซ‹, เชคเซเชฏเชพเชฐเซ‡ เชฎเซ‡เช‚ เชชเชพเชฐเซเชธเชฐ เชฒเช–เชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเชฏเซเช‚ เชœเซ‡ เชฒเซ‡เช–เช•เซ‹เชจเซ€ เชฌเชงเซ€ เชธเชพเชฎเช—เซเชฐเซ€เชจเซ‡ เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชธเชพเชšเชตเชถเซ‡. เชคเซ‡ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฅเชฏเซเช‚ เช…เชจเซ‡ เชฎเชจเซ‡ เช•เชˆ เชญเซ‚เชฒเซ‹ เช†เชตเซ€ - เชคเชฎเซ‡ เช•เชŸ เชนเซ‡เช เชณ เชตเชพเช‚เชšเซ€ เชถเช•เซ‹ เช›เซ‹.

TLDR- เชกเซ‡เชŸเชพเชฌเซ‡เช เชฒเชฟเช‚เช•

เชชเชพเชฐเซเชธเชฐเชจเซเช‚ เชชเซเชฐเชฅเชฎ เชธเช‚เชธเซเช•เชฐเชฃ. เชเช• เชฅเซเชฐเซ‡เชก, เช˜เชฃเซ€ เชธเชฎเชธเซเชฏเชพเช“

เชถเชฐเซเช†เชคเชฎเชพเช‚, เชฎเซ‡เช‚ เชเช• เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชชเซเชฐเซ‹เชŸเซ‹เชŸเชพเช‡เชช เชฌเชจเชพเชตเชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเชฏเซเช‚ เชœเซ‡เชฎเชพเช‚ เชฒเซ‡เช–เชจเซเช‚ เชตเชฟเชถเซเชฒเซ‡เชทเชฃ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡ เช…เชจเซ‡ เชกเชพเช‰เชจเชฒเซ‹เชก เช•เชฐเซเชฏเชพ เชชเช›เซ€ เชคเชฐเชค เชœ เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชฎเซ‚เช•เชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡. เชฌเซ‡ เชตเชพเชฐ เชตเชฟเชšเชพเชฐเซเชฏเชพ เชตเชฟเชจเชพ, เชฎเซ‡เช‚ 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 เช›เซ‡.

เชฌเซ€เชœเซเช‚ เชธเช‚เชธเซเช•เชฐเชฃ. เช˜เชฃเชพ เชฅเซเชฐเซ‡เชกเซ‹, Habr เชคเชฐเชซเชฅเซ€ เช•เชพเชฎเชšเชฒเชพเช‰ เชชเซเชฐเชคเชฟเชฌเช‚เชง

เชœเซเชฏเชพเชฐเซ‡ เชฎเซ‡เช‚ python เชฎเชพเช‚ เชฎเชฒเซเชŸเชฟเชฅเซเชฐเซ‡เชกเซ€เช‚เช—เชจเชพ เชตเชฟเชทเชฏ เชชเชฐ เชˆเชจเซเชŸเชฐเชจเซ‡เชŸเชจเซ€ เชคเชชเชพเชธ เช•เชฐเซ€, เชคเซเชฏเชพเชฐเซ‡ เชฎเซ‡เช‚ multiprocessing.dummy เชธเชพเชฅเซ‡เชจเซ‹ เชธเซŒเชฅเซ€ เชธเชฐเชณ เชตเชฟเช•เชฒเซเชช เชชเชธเช‚เชฆ เช•เชฐเซเชฏเซ‹, เชฎเซ‡เช‚ เชœเซ‹เชฏเซเช‚ เช•เซ‡ เชฎเชฒเซเชŸเชฟเชฅเซเชฐเซ‡เชกเซ€เช‚เช— เชธเชพเชฅเซ‡ เชธเชฎเชธเซเชฏเชพเช“ เชฆเซ‡เช–เชพเชฏ เช›เซ‡.

SQLite3 เชเช• เช•เชฐเชคเชพเช‚ เชตเชงเซ เชฅเซเชฐเซ‡เชก เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพ เชฎเชพเช‚เช—เชคเซเช‚ เชจเชฅเซ€.
เชจเชฟเชถเซเชšเชฟเชค check_same_thread=False, เชชเชฐเช‚เชคเซ เช† เชญเซ‚เชฒ เชเช•เชฎเชพเชคเซเชฐ เชจเชฅเซ€, เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชฆเชพเช–เชฒ เช•เชฐเชตเชพเชจเซ‹ เชชเซเชฐเชฏเชพเชธ เช•เชฐเชคเซ€ เชตเช–เชคเซ‡, เช•เซ‡เชŸเชฒเซ€เช•เชตเชพเชฐ เชญเซ‚เชฒเซ‹ เชฅเชพเชฏ เช›เซ‡ เชœเซ‡ เชนเซเช‚ เชนเชฒ เช•เชฐเซ€ เชถเช•เชคเซ‹ เชจเชฅเซ€.

เชคเซ‡เชฅเซ€, เชนเซเช‚ เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชธเซ€เชงเชพ เชฒเซ‡เช–เซ‹เชจเชพ เชคเซเชตเชฐเชฟเชค เชจเชฟเชตเซ‡เชถเชจเซ‡ เช›เซ‹เชกเซ€ เชฆเซ‡เชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเช‚ เช›เซเช‚ เช…เชจเซ‡, เชเช•เซ€เช•เซƒเชค เช‰เช•เซ‡เชฒเชจเซ‡ เชฏเชพเชฆ เชฐเชพเช–เซ€เชจเซ‡, เชนเซเช‚ เชซเชพเช‡เชฒเซ‹เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเช‚ เช›เซเช‚, เช•เชพเชฐเชฃ เช•เซ‡ เชซเชพเช‡เชฒเชฎเชพเช‚ เชฎเชฒเซเชŸเชฟ-เชฅเซเชฐเซ‡เชกเซ‡เชก เชฒเซ‡เช–เชจ เชธเชพเชฅเซ‡ เช•เซ‹เชˆ เชธเชฎเชธเซเชฏเชพ เชจเชฅเซ€.

Habr เชคเซเชฐเชฃเชฅเซ€ เชตเชงเซ เชฅเซเชฐเซ‡เชกเซ‹เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพ เชชเชฐ เชชเซเชฐเชคเชฟเชฌเช‚เชง เชฎเซ‚เช•เชตเชพเชจเซเช‚ เชถเชฐเซ‚ เช•เชฐเซ‡ เช›เซ‡.
เช–เชพเชธ เช•เชฐเซ€เชจเซ‡ เชนเซ‡เชฌเซเชฐ เชธเซเชงเซ€ เชœเชตเชพเชจเชพ เช‰เชคเซเชธเชพเชนเซ€ เชชเซเชฐเชฏเชพเชธเซ‹ เชฅเซ‹เชกเชพ เช•เชฒเชพเช•เซ‹ เชฎเชพเชŸเซ‡ เช†เชˆเชชเซ€ เชชเซเชฐเชคเชฟเชฌเช‚เชง เชธเชพเชฅเซ‡ เชธเชฎเชพเชชเซเชค เชฅเชˆ เชถเช•เซ‡ เช›เซ‡. เชคเซ‡เชฅเซ€ เชคเชฎเชพเชฐเซ‡ เชซเช•เซเชค 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)

เชคเซเชฐเซ€เชœเซเช‚ เชธเช‚เชธเซเช•เชฐเชฃ. เช…เช‚เชคเชฟเชฎ

เชฌเซ€เชœเชพ เชธเช‚เชธเซเช•เชฐเชฃเชจเซ‡ เชกเชฟเชฌเช— เช•เชฐเชคเซ€ เชตเช–เชคเซ‡, เชฎเซ‡เช‚ เชถเซ‹เชงเซเชฏเซเช‚ เช•เซ‡ Habr, เช…เชšเชพเชจเช•, เชเช• API เช›เซ‡ เชœเซ‡ เชธเชพเช‡เชŸเชจเซเช‚ เชฎเซ‹เชฌเชพเช‡เชฒ เชธเช‚เชธเซเช•เชฐเชฃ เชเช•เซเชธเซ‡เชธ เช•เชฐเซ‡ เช›เซ‡. เชคเซ‡ เชฎเซ‹เชฌเชพเช‡เชฒ เชธเช‚เชธเซเช•เชฐเชฃ เช•เชฐเชคเชพเช‚ เชตเชงเซ เชเชกเชชเชฅเซ€ เชฒเซ‹เชก เชฅเชพเชฏ เช›เซ‡, เช•เชพเชฐเชฃ เช•เซ‡ เชคเซ‡ เชฎเชพเชคเซเชฐ 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

เชเช• เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชฌเชงเชพ Habr

เชฎเซ‡เช‚ เชฆเชฐเซ‡เช• เชฒเซ‡เช–เชจเซ‹ เชธเช‚เชชเซ‚เชฐเซเชฃ json เชกเชฎเซเชช เช•เชฐเซเชฏเซ‹ เชจเชฅเซ€, เชชเชฐเช‚เชคเซ เชฎเชจเซ‡ เชœเชฐเซ‚เชฐเซ€ เชซเซ€เชฒเซเชกเซเชธ เชœ เชธเชพเชšเชตเซเชฏเชพ เช›เซ‡:

  • id
  • เช›เซ‡_เชŸเซเชฏเซเชŸเซ‹เชฐเซ€เชฏเชฒ
  • เชธเชฎเชฏ_เชชเซเชฐเช•เชพเชถเชฟเชค
  • เชถเซ€เชฐเซเชทเช•
  • เชธเชพเชฎเช—เซเชฐเซ€
  • เชŸเชฟเชชเซเชชเชฃเซ€เช“_เช—เชฃเชคเชฐเซ€
  • lang เช เชญเชพเชทเชพ เช›เซ‡ เชœเซ‡เชฎเชพเช‚ เชฒเซ‡เช– เชฒเช–เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡. เช…เชคเซเชฏเชพเชฐ เชธเซเชงเซ€, เชคเซ‡เชฎเชพเช‚ เชซเช•เซเชค en เช…เชจเซ‡ ru เช›เซ‡.
  • เชŸเซ…เช—เซเชธ_เชธเซเชŸเซเชฐเชฟเช‚เช— - เชชเซ‹เชธเซเชŸเชฎเชพเช‚เชฅเซ€ เชฌเชงเชพ เชŸเซ…เช—เซเชธ
  • เชตเชพเช‚เชšเชจ_เช—เชฃเชคเชฐเซ€
  • เชฒเซ‡เช–เช•
  • เชธเซเช•เซ‹เชฐ - เชฒเซ‡เช– เชฐเซ‡เชŸเชฟเช‚เช—.

เช†เชฎ, 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 เชเชฎเชฌเซ€.
  • เช•เซเชฒ, 37804 เชฒเซ‹เช•เซ‹ Habrรฉ เชจเชพ เชฒเซ‡เช–เช•เซ‹ เช›เซ‡. เชนเซเช‚ เชคเชฎเชจเซ‡ เชฏเชพเชฆ เช•เชฐเชพเชตเซเช‚ เช›เซเช‚ เช•เซ‡ เช† เช†เช‚เช•เชกเชพ เชซเช•เซเชค เชฒเชพเช‡เชต เชชเซ‹เชธเซเชŸเชจเชพ เช›เซ‡.
  • เชนเซ‡เชฌเซเชฐเซ‡ เชชเชฐ เชธเซŒเชฅเซ€ เชตเชงเซ เช‰เชคเซเชชเชพเชฆเช• เชฒเซ‡เช–เช• - เช…เชฒเซ€เชเชฐ - 8774 เชฒเซ‡เช–เซ‹.
  • เชŸเซ‹เชšเชจเชพ เชฐเซ‡เชŸเซ‡เชก เชฒเซ‡เช– - 1448 เชตเชคเซเชคเชพ
  • เชธเซŒเชฅเซ€ เชตเชงเซ เชตเชพเช‚เชšเซ‡เชฒเชพ เชฒเซ‡เช– โ€” 1660841 เชœเซ‹เชตเชพเชˆ
  • เชธเซŒเชฅเซ€ เชตเชงเซ เชšเชฐเซเชšเชพเชฏเซ‡เชฒ เชฒเซ‡เช– - 2444 เชŸเชฟเชชเซเชชเชฃเซ€เช“

เชธเชพเชฐเซเช‚, เชŸเซ‹เชšเชจเชพ เชธเซเชตเชฐเซ‚เชชเชฎเชพเช‚เชŸเซ‹เชšเชจเชพ 15 เชฒเซ‡เช–เช•เซ‹เชเช• เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชฌเชงเชพ Habr
เชฐเซ‡เชŸเชฟเช‚เช— เชฆเซเชตเชพเชฐเชพ เชŸเซ‹เชšเชจเชพ 15เชเช• เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชฌเชงเชพ Habr
เชŸเซ‹เชšเชจเชพ 15 เชตเชพเช‚เชšเซ‹เชเช• เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชฌเชงเชพ Habr
เชŸเซ‹เชšเชจเชพ 15 เชšเชฐเซเชšเชพเชเช• เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชฌเชงเชพ Habr

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹