E民䞻䞻矩、たたはモスクワの改修のための投祚および投祚率に関するデヌタを収集および凊理する方法

改修プログラムぞの入堎たたは退堎の投祚が完了するず、䜕らかの理由で、特定の各䜏宅の倖芳に関するデヌタがモスクワ垂長のサむトから消え、党䜓ずしお賛成祚ず反察祚のみが残りたした。 もちろん、いく぀かの数字はニュヌスに曞かれおいたすが、あなたは本圓に自分でそれらを芋お、統蚈をいじり、グラフを䜜成したいのですか

はい、次のようなステヌトメントの埌
これらのサヌビスの人気に関しおは、My Documentsの公共サヌビスセンタヌは投祚者党䜓の半分をやや超えおおり、Active Citizenポヌタルにわずかに負けおいたす。
どういうわけかわずかな疑問がありたす。 だから-情報の収集を始めたしょう そしお、それを分析したす。 これを行うには、ある皮の蚀語たずえばpython、ある皮のデヌタベヌスたずえばsqlite、およびある皮のWebスクレヌパヌが必芁です。これらはpython甚のものが倚いためです。 最埌に、結果のデヌタベヌスぞのリンクを提䟛したすが、それを䜿っお䜕でもできるずすぐに蚀わなければなりたせん。

垂圹所の敷地に行き、車茪を回したす。 4543の家からデヌタを収集する必芁がありたす。 地区リストでランダムな家をクリックしお、デヌタの䞀般的な圢匏を確認したす。

どうやら、すべおの家には特定のIDがあり、URLで確認できたす。

https://www.mos.ru/otvet-stroitelstvo/itogi-golosovaniya-zhitelej-po-proektu-programmy-renovacii/?u=121

したがっお、すべおを自宅で凊理するには、すべおの識別子のリストを取埗しお敎理する必芁があり、各ペヌゞから必芁な情報、぀たり投祚数、反察祚数、合蚈投祚数を取埗したす「未決定」もありたす 「投祚、あるアパヌトで圌らの半分が賛成し、半分が反察する堎合、および䞀般的な家の䌚議があったかどうかなぜですか

IDのリストはどこで入手できたすか 䞊で芋たように、地区リストには指定された家ぞのリンクはありたせん。これは単なる䜏所のテキストリストであり、それだけです。 残念、それは䟿利でしょう。 ここで䞊べ替えを行う必芁があるようです。 ただし、たず、特定の各識別子からデヌタを収集する関数を䜜成したす。

たず、家の取埗リク゚ストを䜜成し、結果の回答を芋お、そこから䜕をスクラップするべきかを理解したす。

 import requests r = requests.get('https://www.mos.ru/otvet-stroitelstvo/itogi-golosovaniya-zhitelej-po-proektu-programmy-renovacii/?u=121') print(r.text) 

応答に投祚デヌタがないこずを知っお驚いた。ある皮のペヌゞテンプレヌトが䞎えられた。 結果のダりンロヌド方法を芋おみたしょう。 そしお実際には-最初にブラりザに未入力のフィヌルドがあるペヌゞがあり、しばらくしおからデヌタが衚瀺されたす。 「開発者向け」の適切なツヌルMozillaなどを備えたブラりザヌを䜿甚しお、そこで䜕が起こるかを正確に確認しおください。



うん いく぀かのapiに察するブラりザリク゚ストが芋぀かりたした。IDは監芖しおいる家のIDず同じです。

぀たり、パラメヌタヌなしでwww.mos.ru/altmosprx/api/1/renovation/house_result/121ぞのgetリク゚ストを送信するず、この皮類のJSONが返されたす。

 { "execTime": 0.044450044631958, "errorMessage": "", "result": { "table": "<table class="table table-big"><thead><tr class="table-header"><td> </td><td> </td><td></td><td></td><td> </td></tr></thead><tbody><tr><td class="apartment-id">0G6O4</td><td class="voting-info"><p>bf659227e8e3</p><p>5f9403659209</p></td><td class="voting-choice"><p></p><p></p></td><td class="voting-date"><p>18.05</p><p>18.05</p></td><td class="apartment-position apartment-agree"><p></p></td></tr><tr><td class="apartment-id">0G6O5</td><td class="voting-info"><p>3f12be5cea77</p></td><td class="voting-choice"><p></p></td><td class="voting-date"><p>15.05</p></td><td class="apartment-position apartment-agree"><p></p></td></tr><tr> ... <td class="apartment-id">0G6V1</td><td class="voting-info"><p>5acd126a410ea1a842e67066ea68fa8f</p></td><td class="voting-choice"><p></p></td><td class="voting-date"><p>24.05</p></td><td class="apartment-position apartment-agree"><p></p></td></tr></tbody></table>", "total": { "und": 0, "za": 100, "protocol_res": 0, "protiv": 0, "gorod_mark": 0, "protocol_date": null, "house_status": 1, "gorod": 0 }, "und_table": "<table class=\"table table-big\"><thead><tr class=\"table-header\"><td> </td><td> </td><td></td><td></td><td> </td></tr></thead><tbody></tbody></table>", "address": " ,  63,  2" }, "request_id": "empty_requestid", "errorCode": 0 } 

さお、ここでは䜕も廃棄する必芁はありたせん。すべおのデヌタはAPIから盎接取埗されたす。 必芁なのは、総䌚に関するアパヌトメントIDの数総投祚数を蚈算し、投祚率に関する既補のデヌタを取埗するこずだけです。

しかし、それでも、どの範囲のIDを芋るのでしょうか 合蚈で4543の家があるはずです。api0を指定したす-そのような家がありたす。 -1を䞎える-゚ラヌ、たあ、ありがずう。 䞋限が決定されたした。 私たちは10000を䞎えたす-そのような家がありたす。 さお、はっきりず4543がありたす。最近参加した領土からいく぀かの家を芋お、䞊郚の境界線をおおよそ決定しおみたしょう...地図に戻り、「叀い」ものから「新しいモスクワ」のどこかに行きたす。玄ココシキノ集萜、ココシキノ䌑暇村、劎働者通り、家2、id440931。たあ、少なくずも50䞇人がいたす。

50䞇のリンクを通垞のルヌプで敎理するのは最善のアむデアではないため、 concurrent.futuresモゞュヌルを䜿甚したす。 もちろん、asyncioのようなものを䜿甚するこずも可胜ですが、そのような倧芏暡なタスクはなく、「小さな血」で行うこずができたす。 すべおが非垞に簡単です。 家番号が明らかに正しい堎合、明らかに間違っおいる堎合、apiが提䟛するものを調べ、すべおをチェックするための関数を䜜成したす。 次に、䞊列ク゚リを䜿甚しおすべおをルヌプでねじりたす。 IDはかなり凊理する必芁がありたす。 次に、結果を䜜成しお曞き留めたす。 䞀般に、次のコヌドのようなものが埗られたす。

 import requests from concurrent.futures import ProcessPoolExecutor import concurrent.futures def check(url): #try  ,   -,    ,     #             try: r = requests.get('https://www.mos.ru/altmosprx/api/1/renovation/house_result/' + str(url) + '/', timeout=10) print(url) r.encoding = 'utf-8' if '400: Bad Request' not in r.text: return str(url) except: #  ,        ,      woops = str(url) + ' failed' return woops results = [] with ProcessPoolExecutor(max_workers=6) as executor: future_results = {executor.submit(check, url): url for url in range(0, 1000000)} #   ,      : url in somelist for future in concurrent.futures.as_completed(future_results): results.append(future.result()) results[:] = [item for item in results if item or item == 0] #check  None,   , ;     ,     with open('/home/deb/mosres.txt', 'w') as f: for item in results: f.write('{}\n'.format(item)) 

私たちはビゞネスに取り掛かりたす-これは6人の劎働者でさえ長い間です。 将来的には、100䞇を凊理した埌、結果よりも70軒少ない家を手に入れたので、このバグパむプを1,000䞇に倉曎しなければならなかったず蚀いたす。 これは長い時間で、仕事を残しお仕事に出たした。
もちろん、䞊列リク゚ストの数を増やすこずは可胜ですが、他の誰かのIPを䜿甚しおいるため、瀌儀正しく振る舞う必芁がありたすそうでなければ、突然犁止されたす。

䞀般に、すべおの家の識別子のリストがありたす。次に、それらを凊理し、利甚可胜なすべおの情報を収集する必芁がありたす。 このような配列は、手でテキストファむルにプッシュするこずはできたせん。凊理するのは䞍䟿です。 sqlite3を䜿甚したす。

デヌタベヌスを䜜成したす。 家ず船䜓、構造などの远加芁玠を陀いお、すべおのフィヌルドは明らかです。 たずえば、近くの家の傟向を芋たい堎合に備えお、取り壊したす。

 import sqlite3 schema = "CREATE TABLE `houses` (\ `id` INTEGER PRIMARY KEY,\ `street` TEXT NOT NULL ,\ `house_nbr` TEXT NOT NULL,\ `house_additional` TEXT,\ `total_votes` INTEGER,\ `total_za` INTEGER,\ `meeting` INTEGER DEFAULT '0',\ `flats` INTEGER\ );" conn = sqlite3.connect('renovation.db') cur = conn.cursor() db = cur.execute(schema) conn.commit() conn.close() 

たあ、ポむントたで すべおのJSON゚ラヌおそらく、回答にJSONがなかったず䞍明な゚ラヌほずんど回答がなかった可胜性が高いを曞き留める方法に沿っお、家に関する情報を取埗しおデヌタベヌスに远加する関数を䜜成したす。もちろん、もしあれば、別々に。

 import requests import re import sqlite3 def gethouseinfo(idd): print(idd) urly = 'https://www.mos.ru/altmosprx/api/1/renovation/house_result/' + str(idd) + '/' try: r = requests.get(urly) r.encoding = 'utf-8' results = r.json() adress = results['result']['address'] print(adress) if re.match('(.*), (.*), (.*)', adress): adress_street = re.match('(.*), (.*), (.*)', adress).group(1) adress_house = re.match('(.*), (.*), (.*)', adress).group(2) adress_building = re.match('(.*), (.*), (.*)', adress).group(3) else: adress_street = re.match('(.*), (.*)', adress).group(1) adress_house = re.match('(.*), (.*)', adress).group(2) adress_building = '' totalvotes = len(re.findall('apartment-id', results['result']['table'])) + len(re.findall('apartment-id', results['result']['und_table'])) aye = results['result']['total']['za'] meetinghappened = bool(results['result']['total']['protocol_res']) iddlist = [] iddlist.append(idd) check = cur.execute('SELECT * FROM houses WHERE id=?', iddlist) res = check.fetchone() if res: print('already exists') else: insert = cur.execute('INSERT INTO houses (id, street, house_nbr, house_additional, total_votes, total_za, meeting) values (?, ?, ?, ?, ?, ?, ?)', [idd, adress_street, adress_house, adress_building, totalvotes, aye, meetinghappened]) print('added ' + str(idd)) except ValueError: print('no data for id '+ str(idd)) jsonerror.append(idd) except: print('unknown eggog') unknownerror.append(idd) jsonerror = [] unknownerror = [] with open('/home/deb/mosres.txt') as fc: mosres = fc.read().splitlines() conn = sqlite3.connect('/home/deb/renovation.db') cur = conn.cursor() for house in mosres: gethouseinfo(house) conn.commit() conn.close() if jsonerror: with open('/home/deb/jsonerror.txt', 'w') as f: for item in jsonerror: f.write('{}\n'.format(item)) if unknownerror: with open('/home/deb/unknownerror.txt', 'w') as f: for item in unknownerror: f.write('{}\n'.format(item)) 

だから、これは䜕かです。 珟圚、垂長宀のりェブサむト䞊の公開情報に基づいお䜜成された、改修の投祚に関するデヌタベヌスがありたす。 すでに掘り䞋げお最終的にグラフィックを描くこずができたす

すべおの結果賛吊䞡論の割合を芖芚的に確認するために小から倧に゜ヌト、X-自宅、プレヌダヌ-の割合、緑の線-䟿宜䞊、克服する必芁がある66を切り捚おる



賛成祚の分垃



これはすべお良いこずですが、倖芳に興味がありたした。 そしお、ここでは難しくなりたす。 実際には、䜏所にアパヌトの数を備えた通垞の、単玔な、集䞭化されたリ゜ヌスはありたせん。 少なくずも2GISには、少なくずも有料情報のアップロヌドの䟋では、アパヌトの数は存圚したすが、有料ですか これは私たちの方法ではありたせん 私たちは他の方法で行きたす。

容赊ないグヌグルずダンデックスは、サむトtvoyadres.ru/domaを指しおおり、そこには、倚くの堎合、アパヌトに関する情報のある家がありたす。 しかし、それらを収集する方法は 理想的には、たずデヌタのある家のリスト党䜓少なくずも通りを収集しおから、垂圹所の圢匏で取埗したデヌタベヌス内の䜏所をこのサむトの圢匏の䜏所に接続しおから、それらを匕き出す必芁がありたす䜕ず結び぀いたのか、アパヌト。 おそらく通りから始める䟡倀はありたすか tvoyadres.ru/ulitsy-しかし、200ペヌゞの゜ヌト、各問題のスクレむピングず凊理は非垞に退屈です。 たぶん、あなたもここでいく぀かのAPIを芋぀けるこずができたすか

街のペヌゞでは成功が埅っおいたした。街のリストだけでなく、「More streets」ボタンもありたす tvoyadres.ru/moskovskaya-oblast/goroda/551



うん タむプリク゚スト
http://tvoyadres.ru/js/street.php?region=81&city=&count=2073&_=1499809159225
は、道路ぞのリンクおよびリンクぞの識別子を含む道路のリストを提䟛したす。 さお、リク゚ストの文字が䜕を意味するのかを理解するこずは残っおいたす。 もちろん、私たちは地域や郜垂にも觊れたせん。 最埌の理解できないものを削陀しお、 tvoyadres.ru / js / street.phpregion = 81city = Moscowcount = 2073のみを残しおみたしょう-結果は同じです。 OK、もう䞀床ボタンをクリックしたす。同じリク゚ストが送信されたしたが、カりントは100少ないこずがわかりたす。 このパラメヌタヌを手動で詊しおみたしょう。

0-゚ラヌが返されたす。 1-1぀の通りが戻りたす。 2-2぀の通りが戻り、すでに1぀を芋おいたす。 100-100通りが返されたした。 200-別の100通りが戻っおきおいたす。 私たちは2073幎に始めたした-2173を詊しおみたせんか はい、これらは街のペヌゞに衚瀺された最初の癟通りです。 2174

重倧な゚ラヌ

SQL構文に゚ラヌがありたす。 行1で '-1、100'の近くで䜿甚する正しい構文に぀いおは、MySQLサヌバヌのバヌゞョンに察応するマニュアルを確認しおください。

おっず。 カりントはLIMIT SELECTク゚リに送られ、制限には垞に100行あるように芋えたすが、最初の行はカりント-2173ずしお蚈算されたす。ちなみに、かなり䞖俗的なようです-SQLむンゞェクションの䜜成方法がわかりたせんでした。それは送信されたせんが、蚈算され、そしおあなたがそれに数字を入れなければ、それは陳腐になりたす。 たあ。 結果がありたす。 さお、ここたでです。

すべおが通垞よりも簡単です

 def getstreets(num): r = requests.get(url + str(num)) results = r.json() result = results['string'] return(result) for i in range(1, 2272, 100): totalres += getstreets(i) 


そしお結果を曞きたす。 結果は、たくさんのhtmlコヌドのようになりたす。 䞀般に、すでにここでは正芏衚珟よりも優れたものに進むこずができたすが、 タスクは非垞に単玔です-それにもかかわらず、私たちは圌らによっおアむデンティティの人々ず䞀緒に街を匕き出し、それから私たちはキヌで圌らの口述を䜜りたす-街の名前。

 sids = re.findall('ulitsy\/(.*?)">(.*?)<\/a>', totalres) #sids = streets with ids streetsdict = {} for i in range(len(sids)): key = sids[i][1] value = sids[i][0] streetsdict[key] = value 

しかし、それから、私たちは通りのペヌゞから家に垰らなければなりたせん、蚀い換えれば-たくさんのhtmlで䜜業したす。 このような䞀連の正芏衚珟を解析しようずするず、より高䟡になりたす。 したがっお、 BeautifulSoupに粟通しおください。

関数を䜜成し、別の蟞曞に察しお実行したす。この堎合、キヌは既に識別子であり、倀はアパヌトメントです。 ロゞックは次のずおりです。アパヌトの名前ごずに、IDごずにIDを取埗できたす。アパヌトを取埗できたす。

 import re from bs4 import BeautifulSoup def gethouses(num): r = requests.get('http://tvoyadres.ru/moskovskaya-oblast/moskva/ulitsy/' + str(num) + '/') results = r.text soup = BeautifulSoup(results, 'html.parser') ul = soup.find("ul", {"class": "next"}) houses = [] try: for li in ul.find_all("li"): urly = li.a['href'] urly = re.search('doma\/(.*)\/', urly).group(1) houses.append([li.get_text(), urly]) return(houses) except: print('None') return('None') totalyres = {} for key in sids: num = sids[key] totalyres[num] = gethouses(num) 

2぀のこずが同時に思い浮かびたす。 たず、各通りにリストがあり、各倀が家の名前ずその識別子を含むリストであるディクテヌションではなく、ディクテヌションが添付されたディクテヌションを䜜成する必芁がありたす。 これは単玔なルヌプに倉えるこずができたす。泚意を集䞭したせんが、そのようなdict totreを呌び出したしょう-はい、ファンタゞヌは最埌に完党に私を残したした。 ごめんなさい

2぀目-そしお各家のyurlには、識別子だけでなく、通りの音蚳も含たれおいたす 䟋 。

 for key in totre: urlo = 'http://tvoyadres.ru/moskovskaya-oblast/moskva/ulitsy/' + key + '/' ra = requests.get(urlo) try: streetname = re.search('<ul class="next"><li><a href="\/moskovskaya-oblast\/moskva\/(.+?)\/doma\/', ra.text).group(1) totre[key]['streetname'] = streetname except: print(key) 

そしお今、私たちはほずんど最も困難に盎面しおいたす。 デヌタベヌスにある垂圹所の番地ず、䜏所録の番地を䜿甚した識別子を結び付ける必芁がありたす。 Difflibはpythonに組み蟌たれおいるため、これに圹立ちたす。 しかし、difflibにはほずんど望みがありたせん。頻床ず類䌌性はもちろん良いので、ナヌザヌが確認する必芁がありたすが、愚かな間違いを避ける必芁がありたす。 䞀般に、フォヌマットを芋るず、クラスずしお文字noがない堎所、道路名から「通り」ずいう単語が削陀されおいる堎所、そしおこれを行うこずに気付きたす。

 conn = sqlite3.connect('renovation.db') cur = conn.cursor() streets = cur.execute('SELECT DISTINCT street FROM houses order by street asc') streeets = streets.fetchall() conn.close() exactmatches = {} keyslist = [] for key in sids.keys(): keyslist.append(key) def glue(maxres=3, freq=0.6): for each in streeets: eachnoyo = each[0].replace('', '') diffres = difflib.get_close_matches(eachnoyo, keyslist, maxres, freq) if each[0] not in exactmatches.keys(): if len(diffres) == 1: print(each[0] + ': ' + diffres[0]) notcompleted = False while notcompleted == False: inp = input('Correct? y/n ') if inp == 'y': notcompleted = True exactmatches[each[0]] = sids[diffres[0]] elif inp == 'n': notcompleted = True else: print('Incorrect input, try again') elif len(diffres) == 0: print('No matches for ' + each[0]) elif len(diffres) > 1: print(each[0] + ': ' + str(diffres)) notcompleted = False while notcompleted == False: inp = input('List number? Or n ') try: listnum = int(inp) except: listnum = None if inp == 'n': notcompleted = True elif listnum in range(0, len(diffres)): notcompleted = True exactmatches[each[0]] = sids[diffres[0]] else: print('Incorrect input, try again') with open('exactmatches.json', 'w') as f: json.dump(exactmatches, f, ensure_ascii=False) 

コン゜ヌルに座っお、結果を芋お、ボタンを抌したす。 サむクル党䜓が終わったら、たずえば、glue10、freq = 0.4など、より倚くのスペアパラメヌタヌで関数を開始したす。



私は、コケックで700通りのうち506通りに忍耐したした。私の意芋では、玠晎らしい結果であり、最も重芁なこずは、統蚈的に有意です最も可胜性が高い。

そしお今、あなたは家のために同じこずをする必芁があり、実際には、その数のアパヌトを取りたす。 そしお、デヌタベヌスに入れたす。

 conn = sqlite3.connect('renovation.db') cur = conn.cursor() allhouses = cur.execute('SELECT * FROM houses WHERE flats IS NULL ORDER BY id') allhousesres = allhouses.fetchall() url2 = 'http://tvoyadres.ru/moskovskaya-oblast/moskva/' def getnumberofflats(streetname, houseid): urlo = url2 + str(streetname) + '/doma/' + str(houseid) + '/' r = requests.get(urlo) results = r.text numbe = re.search('<span class="left"> <\/span> <span class="right">(\d*)<', results).group(1) return numbe def gluehousesnumbers(freq=3, ratio=0.6): for house in allhousesres: if house[1] in exactmatches.keys(): housenbr = house[2].replace('', '') if house[3]: housenbr = housenbr + ' ' + house[3] housenbr = housenbr.lower() diffres = difflib.get_close_matches(housenbr, totre[exactmatches[house[1]]].keys(), freq, ratio) if len(diffres) == 1: print(housenbr + ': ' + diffres[0]) notcompleted = False while notcompleted == False: inp = input('Correct? y/n ') if inp == 'y': notcompleted = True try: flatsnumber = getnumberofflats(totre[exactmatches[house[1]]]['streetname'], totre[exactmatches[house[1]]][diffres[0]]) insertion = cur.execute('UPDATE houses SET flats = ? WHERE id = ?', [flatsnumber, house[0]]) except: print('weird, no flat number for ' + str(house)) elif inp == 'n': notcompleted = True else: print('Incorrect input, try again') elif len(diffres) > 1: print(housenbr + ': ' + str(diffres)) notcompleted = False while notcompleted == False: inp = input('List number? Or n ') try: listnum = int(inp) except: listnum = None if inp == 'n': notcompleted = True elif listnum in range(0, len(diffres)): notcompleted = True try: flatsnumber = getnumberofflats(totre[exactmatches[house[1]]]['streetname'], totre[exactmatches[house[1]]][diffres[0]]) insertion = cur.execute('UPDATE houses SET flats = ? WHERE id = ?', [flatsnumber, house[0]]) except: print('weird, no flat number for ' + str(house)) else: print('Incorrect input, try again') conn.commit() conn.close() 

楜しみ続けおいたす。 䞻なこずは、各関数の実行埌に倉曎をコミットするこずを忘れないこずです。 デヌタベヌスを垞にいじらないように、接続を远加しお関数自䜓にコミットしたせんでした。

はい、それはかなり疲れたす。 しかし、繰り返したすが、すべおをdifflibに委ねるず、「35 'b」よりも「35」に近い「35b」を考慮するスクリヌンショットのように、愚かな間違いが発生したす。 もちろん、これはdifflib゚ラヌではありたせんが、正盎なずころ、完璧なリク゚ストを探すのにもっず時間を費やし、どこかで぀たずくでしょう。 ナヌザヌの確認で最高の、より自信を持っお。



合蚈アパヌトの数は、玄4,500戞のうち3,592戞です 玠晎らしい結果あなたは自分を賞賛したせん-誰も賞賛したせん。 しかし、もちろん、非垞に倚くの偶然の䞀臎が確認された堎合、゚ラヌが発生したす。



アパヌトメントのみず思われるよりも倚くのアパヌトメントが投祚した43のアパヌトメントを削陀したす。 偶然の䞀臎を誀っお確認したか、明らかに間違ったデヌタがあったかは明らかです。

さお、残りの郚分を䜿えば、すでに楜しいこずができたす。 投祚率は、明らかに有暩者の数をアパヌトの数で割ったものずしおカりントされたす。 グラフも明らかに描画されたすが、唯䞀のこずは、投祚による各デヌタポむントに察しお、グラフを描画しおも意味がないこずです。 圱付きの玙のように芋えるので、投祚デヌタを切り䞊げお、このデヌタポむントの平均結果デヌタを取埗するこずをお勧めしたす。

最も近い敎数に䞞める



最も近い5の倍数に䞞めたす。



䞀般に、80の投祚率の領域での䞀察のアンチパむクを陀いお、たたは、さらに遠くを䞞めお芋るず、䞀般に30、40、および80の領域で、投祚率は結果に圱響したせんでした。 驚くべき方法で100の投祚率が垞に100の結果をもたらさない限り。 そしお、平均しお、投祚率は58.7でした。

それは䟡倀がありたしたか 私にずっお、はい、私は倚くを孊びたした。 そしお読者のために さお、読者にはデヌタベヌス自䜓を投皿したす 。

このデヌタでもっず面癜いこずができるかもしれたせん。

Source: https://habr.com/ru/post/J333540/


All Articles