Habr เบ—เบฑเบ‡เปเบปเบ”เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ”เบฝเบง

เบชเบฐโ€‹เบšเบฒเบโ€‹เบ”เบตโ€‹เบ•เบญเบ™โ€‹เบชเบงเบฒเบ. เบกเบฑเบ™เป€เบ›เบฑเบ™เป€เบงเบฅเบฒ 2 เบ›เบตเปเบฅเป‰เบงเบ™เบฑเบšเบ•เบฑเป‰เบ‡เปเบ•เปˆเบ‚เป‰เบญเบเบ‚เบฝเบ™เบกเบฑเบ™ เบšเบปเบ”เบ„เบงเบฒเบกเบชเบธเบ”เบ—เป‰เบฒเบ เบเปˆเบฝเบงเบเบฑเบš Habr paring, เปเบฅเบฐเบšเบฒเบ‡เบชเบดเปˆเบ‡เบšเบฒเบ‡เบขเปˆเบฒเบ‡เป„เบ”เป‰เบกเบตเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡.

เป€เบกเบทเปˆเบญเบ‚เป‰เบญเบเบขเบฒเบเบกเบตเบชเปเบฒเป€เบ™เบปเบฒเบ‚เบญเบ‡ Habr, เบ‚เป‰เบญเบเบ•เบฑเบ”เบชเบดเบ™เปƒเบˆเบ‚เบฝเบ™ parser เบ—เบตเปˆเบˆเบฐเบŠเปˆเบงเบเบ›เบฐเบขเบฑเบ”เป€เบ™เบทเป‰เบญเบซเบฒเบ—เบฑเบ‡เบซเบกเบปเบ”เบ‚เบญเบ‡เบœเบนเป‰เบ‚เบฝเบ™เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™. เบกเบฑเบ™เป€เบเบตเบ”เบ‚เบถเป‰เบ™เปเบ™เบงเปƒเบ”เปเบฅเบฐเบชเบดเปˆเบ‡เบ—เบตเปˆเบ‚เป‰เบญเบเบžเบปเบšเบ‚เปเป‰เบœเบดเบ”เบžเบฒเบ” - เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบญเปˆเบฒเบ™เบžเบฒเบเปƒเบ•เป‰เบเบฒเบ™เบ•เบฑเบ”.

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)

เบ—เบธเบเบชเบดเปˆเบ‡เบ—เบธเบเบขเปˆเบฒเบ‡เปเบกเปˆเบ™เบญเบตเบ‡เบ•เบฒเบกเบ„เบฅเบฒเบชเบชเบดเบ - เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰เปเบเบ‡เบ—เบตเปˆเบชเบงเบเบ‡เบฒเบก, เบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเปเบฅเบฐเบ•เบปเบงเปเบšเบšเป„เบงเปเบกเปˆเบ™เบเบฝเบกเบžเป‰เบญเบก. เบงเปˆเบฒเบžเบฝเบ‡เปเบ•เปˆ ...

  • เบซเบ™เป‰เบฒเป€เบงเบฑเบšเป„เบ”เป‰เบ–เบทเบเบ”เบฒเบงเป‚เบซเบผเบ”เบขเบนเปˆเปƒเบ™เบซเบปเบงเบ‚เปเป‰เบ”เบฝเบง

  • เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบ‚เบฑเบ”เบ‚เบงเบฒเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‚เบญเบ‡ script, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”เบˆเบฐเบšเปเปˆเบขเบนเปˆเปƒเบช. เบซเบผเบฑเบ‡เบˆเบฒเบเบ—เบตเปˆเบ—เบฑเบ‡เบซเบกเบปเบ”, เบ„เปเบฒเบซเบกเบฑเป‰เบ™เบชเบฑเบ™เบเบฒเป„เบ”เป‰เบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เบžเบฝเบ‡เปเบ•เปˆเบซเบผเบฑเบ‡เบˆเบฒเบเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบ—เบฑเบ‡เบซเบกเบปเบ”.
    เปเบ™เปˆเบ™เบญเบ™, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบซเบผเบฑเบ‡เบˆเบฒเบเบเบฒเบ™เปƒเบชเปˆเปเบ•เปˆเบฅเบฐเบ„เบฑเป‰เบ‡, เปเบ•เปˆเป€เบงเบฅเบฒเบ›เบฐเบ•เบดเบšเบฑเบ” script เบˆเบฐเป€เบžเบตเปˆเบกเบ‚เบถเป‰เบ™เบขเปˆเบฒเบ‡เบซเบผเบงเบ‡เบซเบผเบฒเบ.

  • เบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐ 100 เบšเบปเบ”เบ„เบงเบฒเบกเบ—เปเบฒเบญเบดเบ”เปƒเบŠเป‰เป€เบงเบฅเบฒ 000 เบŠเบปเปˆเบงเป‚เบกเบ‡.

เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบŠเบญเบเบซเบฒเบšเบปเบ”เบ„เบงเบฒเบกเบ‚เบญเบ‡เบœเบนเป‰เปƒเบŠเป‰ เบ›เบฐเบชเบปเบกเบ›เบฐเบชเบฒเบ™, เบ—เบตเปˆเบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เบญเปˆเบฒเบ™เปเบฅเบฐเบžเบปเบšเป€เบซเบฑเบ™ hacks เบŠเบตเบงเบดเบ”เบˆเปเบฒเบ™เบงเบ™เบซเบ™เบถเปˆเบ‡เป€เบžเบทเปˆเบญเป€เบฅเบฑเปˆเบ‡เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ™เบตเป‰:

  • เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰ multithreading เป€เบฅเบฑเปˆเบ‡เบเบฒเบ™เบ”เบฒเบงเป‚เบซเบผเบ”เบขเปˆเบฒเบ‡เบซเบผเบงเบ‡เบซเบผเบฒเบ.
  • เบ—เปˆเบฒเบ™เบšเปเปˆเบชเบฒเบกเบฒเบ”เป„เบ”เป‰เบฎเบฑเบšเบชเบฐเบšเบฑเบšเป€เบ•เบฑเบกเบ‚เบญเบ‡ Habr, เปเบ•เปˆเบชเบฐเบšเบฑเบšเบกเบทเบ–เบทเบ‚เบญเบ‡เบกเบฑเบ™.
    เบ•เบปเบงเบขเปˆเบฒเบ‡, เบ–เป‰เบฒเบšเบปเบ”เบ„เบงเบฒเบกเบ›เบฐเบชเบปเบกเบ›เบฐเบชเบฒเบ™เปƒเบ™เบชเบฐเบšเบฑเบš desktop เบกเบตเบ™เป‰เปเบฒเบซเบ™เบฑเบ 378 KB, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เปƒเบ™เบชเบฐเบšเบฑเบšเบกเบทเบ–เบทเบกเบฑเบ™เปเบกเปˆเบ™ 126 KB เปเบฅเป‰เบง.

เบชเบฐเบšเบฑเบšเบ—เบตเบชเบญเบ‡. เบซเบผเบฒเบเบเบฐเบ—เบนเป‰, เบซเป‰เบฒเบกเบŠเบปเปˆเบงเบ„เบฒเบงเบˆเบฒเบ Habr

เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒ scoured เบญเบดเบ™เป€เบ•เบตเป€เบ™เบฑเบ”เบเปˆเบฝเบงเบเบฑเบšเบซเบปเบงเบ‚เปเป‰เบ‚เบญเบ‡ multithreading เปƒเบ™ python เปเบฅเบฐเป€เบฅเบทเบญเบเบ—เบฒเบ‡เป€เบฅเบทเบญเบเบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบเบ—เบตเปˆเบชเบธเบ”เบเบฑเบš multiprocessing.dummy, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบชเบฑเบ‡เป€เบเบ”เป€เบซเบฑเบ™เบงเปˆเบฒเบšเบฑเบ™เบซเบฒเบˆเบฐเบ›เบฒเบเบปเบ”เบžเป‰เบญเบกเบเบฑเบš multithreading.

SQLite3 เบšเปเปˆเบ•เป‰เบญเบ‡เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเบซเบผเบฒเบเบเบงเปˆเบฒเบซเบ™เบถเปˆเบ‡ thread.
เปเบเป‰เป„เบ‚ check_same_thread=False, เปเบ•เปˆเบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”เบ™เบตเป‰เบšเปเปˆเปเบกเปˆเบ™เบญเบฑเบ™เบ”เบฝเบง; เป€เบกเบทเปˆเบญเบžเบฐเบเบฒเบเบฒเบกเปƒเบชเปˆเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™, เบšเบฒเบ‡เบ„เบฑเป‰เบ‡เบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”เป€เบเบตเบ”เบ‚เบทเป‰เบ™เบ—เบตเปˆเบ‚เป‰เบญเบเบšเปเปˆเบชเบฒเบกเบฒเบ”เปเบเป‰เป„เบ‚เป„เบ”เป‰.

เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบ•เบฑเบ”เบชเบดเบ™เปƒเบˆเบ—เบตเปˆเบˆเบฐเบ›เบฐเบ–เบดเป‰เบกเบเบฒเบ™เปเบŠเบเบ—เบฑเบ™เบ—เบตเบ‚เบญเบ‡เบšเบปเบ”เบ„เบงเบฒเบกเป‚เบ”เบเบเบปเบ‡เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เปเบฅเบฐ, เบˆเบทเปˆเบˆเปเบฒเบเบฒเบ™เปเบเป‰เป„เบ‚เบ›เบฐเบชเบปเบกเบ›เบฐเบชเบฒเบ™, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบ•เบฑเบ”เบชเบดเบ™เปƒเบˆเบ—เบตเปˆเบˆเบฐเบ™เปเบฒเปƒเบŠเป‰เป„เบŸเบฅเปŒ, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเบšเปเปˆเบกเบตเบšเบฑเบ™เบซเบฒเบเบฑเบšเบเบฒเบ™เบ‚เบฝเบ™เบซเบผเบฒเบเบเบฐเบ—เบนเป‰เบเบฑเบšเป„เบŸเบฅเปŒ.

Habr เป€เบฅเบตเปˆเบกเบซเป‰เบฒเบกเบเบฒเบ™เปƒเบŠเป‰เบซเบผเบฒเบเบเบงเปˆเบฒเบชเบฒเบกเบเบฐเบ—เบนเป‰.
เบ„เบงเบฒเบกเบžเบฐเบเบฒเบเบฒเบกเบขเปˆเบฒเบ‡เบเบฐเบ•เบทเบฅเบทเบฅเบปเป‰เบ™เป‚เบ”เบเบชเบฐเป€เบžเบฒเบฐเป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเบซเบฒ Habr เบญเบฒเบ”เบˆเบฐเบชเบปเปˆเบ‡เบœเบปเบ™เปƒเบซเป‰เบกเบตเบเบฒเบ™เบซเป‰เบฒเบก IP เบชเปเบฒเบฅเบฑเบšเบชเบญเบ‡เบชเบฒเบกเบŠเบปเปˆเบงเป‚เบกเบ‡. เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เบ—เปˆเบฒเบ™เบˆเบฐเบ•เป‰เบญเบ‡เปƒเบŠเป‰เบžเบฝเบ‡เปเบ•เปˆ 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)

เบชเบฐเบšเบฑเบšเบ—เบตเบชเบฒเบก. เบชเบธเบ”เบ—เป‰เบฒเบ

เปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆ debugging เบชเบฐเบšเบฑเบšเบ—เบตเบชเบญเบ‡, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เบ„เบปเป‰เบ™เบžเบปเบšเบงเปˆเบฒ 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
  • is_tutorial
  • time_published
  • เบซเบปเบงเบ‚เปเป‰
  • เป€เบ™เบทเป‰เบญเปƒเบ™
  • เบ„เบณเป€เบซเบฑเบ™_เบ™เบฑเบš
  • lang เปเบกเปˆเบ™เบžเบฒเบชเบฒเบ—เบตเปˆเบšเบปเบ”เบ‚เบฝเบ™เบ–เบทเบเบ‚เบฝเบ™. เบกเบฒเบฎเบญเบ”เบ›เบฐเบˆเบธเบกเบฑเบ™เบกเบตเบžเบฝเบ‡เปเบ•เปˆ en เปเบฅเบฐ ru.
  • tags_string โ€” tags เบ—เบฑเบ‡โ€‹เบซเบกเบปเบ”โ€‹เบˆเบฒเบโ€‹เบเบฒเบ™โ€‹เบ•เบญเบšโ€‹
  • เบญเปˆเบฒเบ™_เบ™เบฑเบš
  • เบœเบนเป‰โ€‹เบ›เบฐโ€‹เบžเบฑเบ™
  • เบ„เบฐโ€‹เปเบ™เบ™ โ€” rating เบšเบปเบ”โ€‹เบ„เบงเบฒเบกโ€‹.

เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰ API, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เบซเบผเบธเบ”เบฅเบปเบ‡เป€เบงเบฅเบฒเบ›เบฐเบ•เบดเบšเบฑเบ”เบชเบฐเบ„เบดเบšเป€เบ›เบฑเบ™ 8 เบงเบดเบ™เบฒเบ—เบตเบ•เปเปˆ 100 url.

เบซเบผเบฑเบ‡เบˆเบฒเบเบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ”เบฒเบงเป‚เบซเบฅเบ”เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบเบฒเบ™, เบžเบงเบเป€เบฎเบปเบฒเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบ›เบธเบ‡เปเบ•เปˆเบ‡เบกเบฑเบ™เปเบฅเบฐเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™. เบšเปเปˆเบกเบตเบšเบฑเบ™เบซเบฒเบเบฑเบšเป€เบฅเบทเปˆเบญเบ‡เบ™เบตเป‰:

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 เบšเบปเบ”เบ„เบงเบฒเบกเบ–เบทเบเบ”เบฒเบงเป‚เบซเบผเบ”. เบกเบฑเบ™ turns เปƒเบซเป‰ เป€เบซเบฑเบ™ เบงเปˆเบฒ เบซเบผเบฒเบ เบ เปˆ เบงเบฒ เป€เบ„เบดเปˆเบ‡ เบซเบ™เบถเปˆเบ‡ (228) เบ‚เบญเบ‡ เบšเบปเบ” เบ„เบงเบฒเบก เบเปˆเบฝเบง เบเบฑเบš Habrรฉ เป„เบ”เป‰ เบ–เบทเบ เป€เบŠเบทเปˆเบญเบ‡ เป„เบงเป‰ เบซเบผเบท เบฅเบถเบš.
  • เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”, เบ›เบฐเบเบญเบšเบ”เป‰เบงเบเป€เบเบทเบญเบšเป€เบ„เบดเปˆเบ‡เบซเบ™เบถเปˆเบ‡เบฅเป‰เบฒเบ™เบšเบปเบ”เบ„เบงเบฒเบก, เบ™เป‰เปเบฒเบซเบ™เบฑเบ 2.95 GB. เปƒเบ™เบฎเบนเบšเปเบšเบšเบšเบตเบšเบญเบฑเบ” - 495 MB.
  • เปƒเบ™เบˆเปเบฒเบ™เบงเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”, เบกเบต 37804 เบœเบนเป‰เบ‚เบฝเบ™เปƒเบ™Habre. เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบ‚เปเป€เบ•เบทเบญเบ™เบ—เปˆเบฒเบ™เบงเปˆเบฒเป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เปเบกเปˆเบ™เบชเบฐเบ–เบดเบ•เบดเบžเบฝเบ‡เปเบ•เปˆเบˆเบฒเบเบ‚เปเป‰เบ„เบงเบฒเบกเบชเบปเบ”.
  • เบœเบนเป‰เบ‚เบฝเบ™เบ—เบตเปˆเบกเบตเบ›เบฐเป‚เบซเบเบ”เบชเบนเบ‡เบชเบธเบ”เปƒเบ™ Habre - เบญเบฒเบฅเบดเบŠเบฒ โ€” 8774 เบšเบปเบ”โ€‹เบ„เบงเบฒเบกโ€‹.
  • เบšเบปเบ”เบ„เบงเบฒเบกเบญเบฑเบ™เบ”เบฑเบšเบชเบนเบ‡เบชเบธเบ” โ€” 1448 pluses
  • เบšเบปเบ”เบ„เบงเบฒเบกเบ—เบตเปˆเบญเปˆเบฒเบ™เบซเบผเบฒเบเบ—เบตเปˆเบชเบธเบ” - 1660841 views
  • เบชเปˆเบงเบ™เบซเบผเบฒเบเปเบกเปˆเบ™เป€เบงเบปเป‰เบฒเป€เบ–เบดเบ‡เบšเบปเบ”เบ„เบงเบฒเบก โ€” 2444 เบ„เปเบฒโ€‹เป€เบซเบฑเบ™

เบ”เบต, เปƒเบ™เบฎเบนเบšเปเบšเบšเบ‚เบญเบ‡ topsเบœเบนเป‰เบ‚เบฝเบ™ 15 เบญเบฑเบ™เบ”เบฑเบšเบ•เบปเป‰เบ™Habr เบ—เบฑเบ‡เปเบปเบ”เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ”เบฝเบง
เบญเบฑเบ™เบ”เบฑเบš 15 เป‚เบ”เบเบเบฒเบ™เบˆเบฑเบ”เบญเบฑเบ™เบ”เบฑเบšHabr เบ—เบฑเบ‡เปเบปเบ”เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ”เบฝเบง
เบญเบฑเบ™เบ”เบฑเบš 15 เบญเปˆเบฒเบ™Habr เบ—เบฑเบ‡เปเบปเบ”เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ”เบฝเบง
เบชเบธเบ”เบเบญเบ” 15 เบชเบปเบ™เบ—เบฐเบ™เบฒHabr เบ—เบฑเบ‡เปเบปเบ”เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ”เบฝเบง

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™