ဒေတာဘေ့စ်တစ်ခုတည်သတလင် Habr အာသလုံသ

မင်္ဂလာနေ့လည်ခင်သပါ။ ရေသထာသတာ ၂ နဟစ်ရဟိပဌီ။ နောက်ဆုံသဆောင်သပါသ Habr ကိုခလဲခဌမ်သစိတ်ဖဌာခဌင်သနဟင့်ပတ်သက်ပဌီသအချို့အချက်မျာသပဌောင်သလဲသလာသသည်။

Habr မိတ္တူကို လိုချင်သောအခါ၊ စာရေသသူ၏ အကဌောင်သအရာအာသလုံသကို ဒေတာဘေ့စ်တလင် သိမ်သဆည်သမည့် parser တစ်ခုရေသရန် ဆုံသဖဌတ်ခဲ့သည်။ ဘယ်လို အမဟာသအယလင်သတလေ ကဌုံခဲ့ရသလဲ ဆိုတာကို အောက်မဟာ ဖတ်ရဟုနိုင်ပါတယ်။

TLDR- ဒေတာဘေ့စ်လင့်ခ်

parser ၏ပထမဗာသရဟင်သ။ ကဌိုသတစ်ချောင်သ၊ ပဌဿနာမျာသစလာ

အစအာသဖဌင့်၊ ဆောင်သပါသကို ခလဲခဌမ်သစိပ်ဖဌာပဌီသ ဒေါင်သလုဒ်ဆလဲပဌီသသည်နဟင့် ချက်ချင်သဆိုသလို ဒေတာဘေ့စ်တလင် ထာသရဟိမည့် script prototype တစ်ခုကို ပဌုလုပ်ရန် ဆုံသဖဌတ်ခဲ့သည်။ နဟစ်ခါမစဉ်သစာသဘဲ 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 နာရီ ကဌာပါသည်။

နောက်တစ်ခုကတော့ အသုံသပဌုသူရဲ့ ဆောင်သပါသကို ရဟာပါတယ်။ ပေါင်သစပ်ထာသသည်။ကလုပ်ငန်သစဉ်ကို အရဟိန်မဌဟင့်ရန် ဘဝဟက်ခ်အချို့ကို ကျလန်ုပ်ဖတ်ရဟုပဌီသ တလေ့ရဟိခဲ့သည်-

  • Multithreading ကိုအသုံသပဌုခဌင်သသည် တစ်ခါတစ်ရံတလင် ဒေါင်သလုဒ်ဆလဲခဌင်သကို မဌန်ဆန်စေသည်။
  • habr ၏ ဗာသရဟင်သအပဌည့်အစုံမဟုတ်သော်လည်သ ၎င်သ၏မိုဘိုင်သဗာသရဟင်သကို သင်ရနိုင်သည်။
    ဥပမာအာသဖဌင့်၊ ဒက်စ်တော့ဗာသရဟင်သတလင် ပေါင်သစပ်ထာသသော ဆောင်သပါသတစ်ပုဒ်သည် 378 KB အလေသချိန်ရဟိလျဟင် မိုဘိုင်သဗာသရဟင်သတလင် ၎င်သသည် 126 KB ရဟိပဌီသဖဌစ်သည်။

ဒုတိယဗာသရဟင်သ။ စာတလဲမျာသစလာ၊ Habr မဟ ယာယီပိတ်ပင်ထာသသည်။

python တလင် multithreading ခေါင်သစဉ်ဖဌင့်အင်တာနက်ကိုလေ့လာကဌည့်သောအခါ multiprocessing.dummy ဖဌင့်အရိုသရဟင်သဆုံသရလေသချယ်မဟုကိုရလေသချယ်ခဲ့ပဌီသ multithreading နဟင့်အတူပဌဿနာမျာသပေါ်လာသည်ကိုသတိပဌုမိခဲ့သည်။

SQLite3 သည် thread တစ်ခုထက်ပို၍ အလုပ်မလုပ်လိုပါ။.
သတ်မဟတ်ထာသတဲ့ check_same_thread=Falseဒါပေမယ့် ဒီ error က တစ်ခုတည်သ မဟုတ်ပါဘူသ၊ database ထဲကို ထည့်ဖို့ ကဌိုသစာသတဲ့အခါ တခါတရံ ကျလန်တော် မဖဌေရဟင်သနိုင်တဲ့ errors တလေ ဖဌစ်ပေါ်လာပါတယ်။

ထို့ကဌောင့်၊ ဒေတာဘေ့စ်ထဲသို့ ဆောင်သပါသမျာသ တိုက်ရိုက်ထည့်သလင်သခဌင်သကို စလန့်လလဟတ်ရန် ဆုံသဖဌတ်ပဌီသ ပေါင်သစပ်ပေါင်သစပ်ဖဌေရဟင်သချက်ကို သတိရကာ ဖိုင်တစ်ခုသို့ ကဌိုသတန်သစုံရေသခဌင်သတလင် ပဌဿနာမရဟိသောကဌောင့် ဖိုင်မျာသကို အသုံသပဌုရန် ဆုံသဖဌတ်ခဲ့သည်။

Habr သည် thread သုံသခုထက်ပို၍အသုံသပဌုခဌင်သအတလက် တာသမဌစ်ခဌင်သစတင်သည်။.
အထူသသဖဌင့် 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)

တတိယဗာသရဟင်သ။ နောက်ဆုံသ

ဒုတိယဗာသရဟင်သကို အမဟာသရဟာပဌင်နေစဉ်၊ Habr သည် ဆိုက်၏မိုဘိုင်သဗာသရဟင်သသို့ဝင်ရောက်သည့် API တစ်ခုပါရဟိသည်ကို ရုတ်တရက် တလေ့ရဟိခဲ့သည်။ ခလဲခဌမ်သစိတ်ဖဌာရန်ပင်မလိုအပ်သော json မျဟသာဖဌစ်သောကဌောင့်၎င်သသည်မိုဘိုင်သဗာသရဟင်သထက်ပိုမိုမဌန်ဆန်သည်။ နောက်ဆုံသတော့ ကျလန်တော့် ဇာတ်ညလဟန်သကို ပဌန်ရေသဖို့ ဆုံသဖဌတ်လိုက်တယ်။

ဒါဆို တလေ့ပဌီပေါ့။ ဒီ link ကို 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 သာရဟိသည်။
  • tags_string - ပို့စ်မဟ တဂ်မျာသအာသလုံသ
  • စာဖတ်ခဌင်သ_အရေအတလက်
  • စာရေသသူ
  • ရမဟတ် - ဆောင်သပါသအဆင့်သတ်မဟတ်ချက်။

ထို့ကဌောင့် API ကိုအသုံသပဌု၍ url 8 တစ်ခုလျဟင် script လည်ပတ်ချိန်ကို 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)

စာရင်သအင်သ

ကောင်သပဌီ၊ အစဉ်အလာအာသဖဌင့်၊ နောက်ဆုံသတလင်၊ သင်သည် အချက်အလက်အချို့မဟ ကိန်သဂဏန်သအချက်အလက်မျာသကို ထုတ်ယူနိုင်သည်-

  • ဒေါင်သလုဒ်လုပ်ရန် မျဟော်မဟန်သထာသသည့် ၄၉၀,၄၀၆ အနက်၊ ဆောင်သပါသ ၂၂၈,၅၁၂ သာ ဒေါင်သလုဒ်လုပ်ခဲ့သည်။ Habré ပေါ်ရဟိ ဆောင်သပါသမျာသ၏ ထက်ဝက်ကျော် (490) ကို ဝဟက်ထာသသည် သို့မဟုတ် ဖျက်လိုက်ကဌောင်သ တလေ့ရဟိရသည်။
  • ဆောင်သပါသပေါင်သ တစ်သန်သခလဲနီသပါသ ပါဝင်သော ဒေတာဘေ့စ်တစ်ခုလုံသသည် 2.95 GB အလေသချိန်ရဟိသည်။ ချုံ့ပုံစံ - 495 MB ။
  • စုစုပေါင်သ ၃၇၈၀၄ ညသသည် Habre ၏စာရေသဆရာမျာသဖဌစ်သည်။ ကစာရင်သဇယာသမျာသသည် တိုက်ရိုက်လလဟင့်တင်မဟုမျာသမဟသာဖဌစ်ကဌောင်သ သင့်အာသ ကျလန်ုပ်သတိပေသပါသည်။
  • Habre တလင် အကျိုသအရဟိဆုံသ စာရေသဆရာ- အလီဇာ ဆောင်သပါသ - ၈၇၇၄။
  • ထိပ်တန်သအဆင့်သတ်မဟတ်ထာသသော ဆောင်သပါသ 1448 pluses
  • အမျာသဆုံသဖတ်သောဆောင်သပါသ - ကဌည့်ရဟုမဟု 1660841
  • ဆလေသနလေသမဟုအမျာသဆုံသဆောင်သပါသ မဟတ်ချက် - ၂၄၄၄

ကောင်သပဌီ, ထိပ်၏ပုံစံထိပ်တန်သစာရေသဆရာ ၁၅ ညသဒေတာဘေ့စ်တစ်ခုတည်သတလင် Habr အာသလုံသ
အဆင့်သတ်မဟတ်ချက်အရ ထိပ်တန်သ 15ဒေတာဘေ့စ်တစ်ခုတည်သတလင် Habr အာသလုံသ
ထိပ်တန်သ 15 ဖတ်ဒေတာဘေ့စ်တစ်ခုတည်သတလင် Habr အာသလုံသ
ထိပ်တန်သ 15 ခု ဆလေသနလေသခဲ့သည်။ဒေတာဘေ့စ်တစ်ခုတည်သတလင် Habr အာသလုံသ

source: www.habr.com

မဟတ်ချက် Add