ΠΠΎΠ±ΡΡ Π΄Π΅Π½. ΠΠΈΠ½Π°Ρ
Π° 2 Π³ΠΎΠ΄ΠΈΠ½ΠΈ ΠΎΡΠΊΠ°ΠΊΡΠΎ Π΅ Π½Π°ΠΏΠΈΡΠ°Π½ΠΎ.
ΠΠΎΠ³Π°ΡΠΎ ΠΈΡΠΊΠ°Ρ Π΄Π° ΠΈΠΌΠ°ΠΌ ΠΊΠΎΠΏΠΈΠ΅ Π½Π° 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)
ΠΡΠΈΡΠΊΠΎ Π΅ ΠΊΠ»Π°ΡΠΈΡΠ΅ΡΠΊΠΎ - ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Beautiful Soup, Π·Π°ΡΠ²ΠΊΠΈ ΠΈ Π±ΡΡΠ· ΠΏΡΠΎΡΠΎΡΠΈΠΏ Π΅ Π³ΠΎΡΠΎΠ². Π’ΠΎΠ²Π° Π΅ ΠΏΡΠΎΡΡΠΎβ¦
-
ΠΠ·ΡΠ΅Π³Π»ΡΠ½Π΅ΡΠΎ Π½Π° ΡΡΡΠ°Π½ΠΈΡΠ°ΡΠ° Π΅ Π² Π΅Π΄Π½Π° Π½ΠΈΡΠΊΠ°
-
ΠΠΊΠΎ ΠΏΡΠ΅ΠΊΡΡΠ½Π΅ΡΠ΅ ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅ΡΠΎ Π½Π° ΡΠΊΡΠΈΠΏΡΠ°, ΡΠΎΠ³Π°Π²Π° ΡΡΠ»Π°ΡΠ° Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ Π½ΡΠΌΠ° Π΄Π° ΠΎΡΠΈΠ΄Π΅ Π½ΠΈΠΊΡΠ΄Π΅. Π ΠΊΡΠ°Ρ Π½Π° ΠΊΡΠ°ΠΈΡΠ°ΡΠ° Π°Π½Π³Π°ΠΆΠΈΠΌΠ΅Π½ΡΡΡ ΡΠ΅ ΠΈΠ·Π²ΡΡΡΠ²Π° ΡΠ°ΠΌΠΎ ΡΠ»Π΅Π΄ Π²ΡΠΈΡΠΊΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈ.
Π Π°Π·Π±ΠΈΡΠ° ΡΠ΅, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·Π²ΡΡΡΠ²Π°ΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ Π² Π±Π°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ ΡΠ»Π΅Π΄ Π²ΡΡΠΊΠΎ Π²ΠΌΡΠΊΠ²Π°Π½Π΅, Π½ΠΎ ΡΠΎΠ³Π°Π²Π° Π²ΡΠ΅ΠΌΠ΅ΡΠΎ Π·Π° ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅ Π½Π° ΡΠΊΡΠΈΠΏΡΠ° ΡΠ΅ ΡΠ΅ ΡΠ²Π΅Π»ΠΈΡΠΈ Π·Π½Π°ΡΠΈΡΠ΅Π»Π½ΠΎ. -
Π Π°Π·Π±ΠΎΡΡΡ Π½Π° ΠΏΡΡΠ²ΠΈΡΠ΅ 100 000 ΡΡΠ°ΡΠΈΠΈ ΠΌΠΈ ΠΎΡΠ½Π΅ 8 ΡΠ°ΡΠ°.
Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° Π½Π°ΠΌΠΈΡΠ°ΠΌ ΡΡΠ°ΡΠΈΡΡΠ° Π½Π° ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»Ρ
- ΠΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ΡΠΎ Π½Π° ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡΠΎΡΠ½ΠΎΡΡ ΡΡΠΊΠΎΡΡΠ²Π° ΠΈΠ·ΡΠ΅Π³Π»ΡΠ½Π΅ΡΠΎ Π² ΠΏΡΡΠΈ.
- ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΠΎΠ»ΡΡΠΈΡΠ΅ Π½Π΅ ΠΏΡΠ»Π½Π°ΡΠ° Π²Π΅ΡΡΠΈΡ Π½Π° habr, Π° Π½Π΅Π³ΠΎΠ²Π°ΡΠ° ΠΌΠΎΠ±ΠΈΠ»Π½Π° Π²Π΅ΡΡΠΈΡ.
ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π°ΠΊΠΎ ΠΊΠΎΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠ°Π½Π° ΡΡΠ°ΡΠΈΡ Π² Π½Π°ΡΡΠΎΠ»Π½Π°ΡΠ° Π²Π΅ΡΡΠΈΡ ΡΠ΅ΠΆΠΈ 378 KB, ΡΠΎ Π² ΠΌΠΎΠ±ΠΈΠ»Π½Π°ΡΠ° Π²Π΅ΡΡΠΈΡ ΡΡ Π²Π΅ΡΠ΅ Π΅ 126 KB.
ΠΡΠΎΡΠ° Π²Π΅ΡΡΠΈΡ. ΠΠ½ΠΎΠ³ΠΎ ΡΠ΅ΠΌΠΈ, Π²ΡΠ΅ΠΌΠ΅Π½Π½Π° Π·Π°Π±ΡΠ°Π½Π° ΠΎΡ Habr
ΠΠΎΠ³Π°ΡΠΎ ΠΏΡΠ΅ΡΡΡΡΠΈΡ ΠΈΠ½ΡΠ΅ΡΠ½Π΅Ρ ΠΏΠΎ ΡΠ΅ΠΌΠ°ΡΠ° Π·Π° ΠΌΠ½ΠΎΠ³ΠΎΠ½ΠΈΡΠΊΠΎΠ²ΠΎΡΡΡΠ° Π² python, ΠΈΠ·Π±ΡΠ°Ρ Π½Π°ΠΉ-ΠΏΡΠΎΡΡΠ°ΡΠ° ΠΎΠΏΡΠΈΡ Ρ multiprocessing.dummy, Π·Π°Π±Π΅Π»ΡΠ·Π°Ρ , ΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈΡΠ΅ ΡΠ΅ ΠΏΠΎΡΠ²ΡΠ²Π°Ρ Π·Π°Π΅Π΄Π½ΠΎ Ρ ΠΌΠ½ΠΎΠ³ΠΎΠ½ΠΈΡΠΊΠΎΠ²ΠΎΡΡΡΠ°.
SQLite3 Π½Π΅ ΠΈΡΠΊΠ° Π΄Π° ΡΠ°Π±ΠΎΡΠΈ Ρ ΠΏΠΎΠ²Π΅ΡΠ΅ ΠΎΡ Π΅Π΄Π½Π° Π½ΠΈΡΠΊΠ°.
ΡΠΈΠΊΡΠΈΡΠ°Π½ΠΈ 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)
Π’ΡΠ΅ΡΠ° Π²Π΅ΡΡΠΈΡ. Π€ΠΈΠ½Π°Π»
ΠΠΎΠΊΠ°ΡΠΎ ΠΎΡΡΡΡΠ°Π½ΡΠ²Π°Ρ Π³ΡΠ΅ΡΠΊΠΈ Π²ΡΠ² Π²ΡΠΎΡΠ°ΡΠ° Π²Π΅ΡΡΠΈΡ, ΠΎΡΠΊΡΠΈΡ , ΡΠ΅ Habr ΠΈΠ·Π²Π΅Π΄Π½ΡΠΆ ΠΈΠΌΠ° API, Π΄ΠΎ ΠΊΠΎΠΉΡΠΎ ΠΌΠΎΠ±ΠΈΠ»Π½Π°ΡΠ° Π²Π΅ΡΡΠΈΡ Π½Π° ΡΠ°ΠΉΡΠ° ΠΈΠΌΠ° Π΄ΠΎΡΡΡΠΏ. ΠΠ°ΡΠ΅ΠΆΠ΄Π° ΡΠ΅ ΠΏΠΎ-Π±ΡΡΠ·ΠΎ ΠΎΡ ΠΌΠΎΠ±ΠΈΠ»Π½Π°ΡΠ° Π²Π΅ΡΡΠΈΡ, ΡΡΠΉ ΠΊΠ°ΡΠΎ Π΅ ΡΠ°ΠΌΠΎ json, ΠΊΠΎΠΉΡΠΎ Π΄ΠΎΡΠΈ Π½Π΅ ΡΡΡΠ±Π²Π° Π΄Π° ΡΠ΅ Π°Π½Π°Π»ΠΈΠ·ΠΈΡΠ°. Π ΠΊΡΠ°ΠΉΠ½Π° ΡΠΌΠ΅ΡΠΊΠ° ΡΠ΅ΡΠΈΡ Π΄Π° ΠΏΡΠ΅Π½Π°ΠΏΠΈΡΠ° ΠΎΡΠ½ΠΎΠ²ΠΎ ΡΡΠ΅Π½Π°ΡΠΈΡ ΡΠΈ.
Π ΡΠ°ΠΊΠ°, ΡΠ»Π΅Π΄ ΠΊΠ°ΡΠΎ Π½Π°ΠΌΠ΅ΡΠΈ
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
- is_tutorial
- time_published
- Π·Π°Π³Π»Π°Π²ΠΈΠ΅
- ΡΡΠ΄ΡΡΠΆΠ°Π½ΠΈΠ΅
- comments_count
- lang Π΅ Π΅Π·ΠΈΠΊΡΡ, Π½Π° ΠΊΠΎΠΉΡΠΎ Π΅ Π½Π°ΠΏΠΈΡΠ°Π½Π° ΡΡΠ°ΡΠΈΡΡΠ°. ΠΠ°ΡΠ΅Π³Π° ΠΈΠΌΠ° ΡΠ°ΠΌΠΎ en ΠΈ ru.
- tags_string - Π²ΡΠΈΡΠΊΠΈ ΡΠ°Π³ΠΎΠ²Π΅ ΠΎΡ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΡΡΠ°
- reading_count
- Π°Π²ΡΠΎΡ
- ΠΎΡΠ΅Π½ΠΊΠ° β ΠΎΡΠ΅Π½ΠΊΠ° Π½Π° ΡΡΠ°ΡΠΈΡΡΠ°.
ΠΠΎ ΡΠΎΠ·ΠΈ Π½Π°ΡΠΈΠ½, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ 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 ΠΈΠ·ΡΠ΅Π³Π»ΡΠ½ΠΈΡ Π±ΡΡ Π° ΠΈΠ·ΡΠ΅Π³Π»Π΅Π½ΠΈ ΡΠ°ΠΌΠΎ 228 512 ΡΡΠ°ΡΠΈΠΈ. ΠΠΊΠ°Π·Π²Π° ΡΠ΅, ΡΠ΅ ΠΏΠΎΠ²Π΅ΡΠ΅ ΠΎΡ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π°ΡΠ° (261894) ΠΎΡ ΡΡΠ°ΡΠΈΠΈΡΠ΅ Π½Π° Π₯Π°Π±ΡΠ΅ ΡΠ° ΡΠΊΡΠΈΡΠΈ ΠΈΠ»ΠΈ ΠΈΠ·ΡΡΠΈΡΠΈ.
- Π¦ΡΠ»Π°ΡΠ° Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ, ΡΡΡΡΠΎΡΡΠ° ΡΠ΅ ΠΎΡ ΠΏΠΎΡΡΠΈ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½ ΠΌΠΈΠ»ΠΈΠΎΠ½ ΡΡΠ°ΡΠΈΠΈ, ΡΠ΅ΠΆΠΈ 2.95 GB. Π ΠΊΠΎΠΌΠΏΡΠ΅ΡΠΈΡΠ°Π½ Π²ΠΈΠ΄ - 495 MB.
- ΠΠ±ΡΠΎ 37804 Π΄ΡΡΠΈ ΡΠ° Π°Π²ΡΠΎΡΠΈ Π½Π° Π₯Π°Π±ΡΠ΅. ΠΠ°ΠΏΠΎΠΌΠ½ΡΠΌ Π²ΠΈ, ΡΠ΅ ΡΠ°Π·ΠΈ ΡΡΠ°ΡΠΈΡΡΠΈΠΊΠ° Π΅ ΡΠ°ΠΌΠΎ ΠΎΡ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ Π½Π° ΠΆΠΈΠ²ΠΎ.
- ΠΠ°ΠΉ-ΠΏΡΠΎΠ΄ΡΠΊΡΠΈΠ²Π½ΠΈΡΡ Π°Π²ΡΠΎΡ Π½Π° Π₯Π°Π±ΡΠ΅ -
Π°Π»ΠΈΠ·Π°Ρ - 8774 ΡΡΠ°ΡΠΈΠΈ. ΠΠ°ΠΉ-Π²ΠΈΡΠΎΠΊΠΎ ΠΎΡΠ΅Π½Π΅Π½Π° ΡΡΠ°ΡΠΈΡ β 1448 ΠΏΠ»ΡΡΠ°ΠΠ°ΠΉ-ΡΠ΅ΡΠ΅Π½Π° ΡΡΠ°ΡΠΈΡ β 1660841 ΠΏΠΎΠΊΠ°Π·Π²Π°Π½ΠΈΡΠΠ°ΠΉ-ΠΎΠ±ΡΡΠΆΠ΄Π°Π½Π° ΡΡΠ°ΡΠΈΡ β 2444 ΠΊΠΎΠΌΠ΅Π½ΡΠ°ΡΠ°
Π, ΠΏΠΎΠ΄ ΡΠΎΡΠΌΠ°ΡΠ° Π½Π° Π²ΡΡΡ
ΠΎΠ²Π΅Π’ΠΎΠΏ 15 Π°Π²ΡΠΎΡΠΈ
Π’ΠΎΠΏ 15 ΠΏΠΎ ΡΠ΅ΠΉΡΠΈΠ½Π³
Π’ΠΎΠΏ 15 ΠΏΡΠΎΡΠ΅ΡΠ΅Π½ΠΈ
ΠΠ±ΡΡΠΆΠ΄Π°Π½ΠΈ ΡΠΎΠΏ 15
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: www.habr.com