Advertisement
Qwentor

Untitled

Mar 14th, 2020
461
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.74 KB | None | 0 0
  1. import asyncio
  2. import nest_asyncio
  3. import pyppeteer
  4. from pyppeteer import launch
  5. from pprint import pprint
  6. import requests
  7. import base64
  8. import json
  9. import os
  10. import aiofiles
  11. import random
  12. from pyquery import PyQuery as pq
  13. import aiosqlite
  14. from datetime import datetime
  15. import regex
  16. from urllib.parse import urlparse
  17. import idna
  18. import configparser
  19. from flask import Flask, flash, redirect, render_template, request, session, abort, url_for
  20. from multiprocessing import Process
  21. import sqlite3
  22. import tkinter as tk
  23. from tkinter import filedialog
  24. from tkinter.ttk import Progressbar
  25. from tkinter import OptionMenu
  26. from tkinter import StringVar
  27. from tkinter import messagebox
  28. from tkinter import Label
  29. from tkinter import Entry
  30. from tkinter import Button
  31. import tkinter.font as font
  32. import psutil
  33.  
  34.  
  35. config = configparser.ConfigParser()
  36. config.read('settings.ini')
  37.  
  38. BASEDIR = os.path.dirname(os.path.realpath(__file__))
  39.  
  40. def get_as_base64(url):
  41.     return base64.b64encode(requests.get(url).content).decode('utf8')
  42.  
  43.  
  44. def dict_factory(cursor, row):
  45.     d = {}
  46.     for idx, col in enumerate(cursor.description):
  47.         d[col[0]] = row[idx]
  48.     return d
  49.  
  50. f = open(os.path.join(BASEDIR, config['PARSER']['Proxies']), mode='r', encoding="utf-8")
  51. proxies = f.readlines()
  52. f.close()
  53. proxies = [x.strip() for x in proxies if x != '']
  54.  
  55. f = open(os.path.join(BASEDIR, config['PARSER']['Queries']), mode='r', encoding="utf-8")
  56. queries = f.readlines()
  57. f.close()
  58. queries = [x.strip() for x in queries if x != '']
  59. random.shuffle(queries)
  60.  
  61.  
  62.  
  63. async def fetch(query, proxy):
  64.     print('START PROCESS')
  65.  
  66.    
  67.     print('TEST')
  68.     browser = await launch(headless=True, args=['--no-sandbox', '--proxy-server='+proxy, ])
  69.     print(4)
  70.     try:
  71.         page = await browser.newPage()
  72.         await page.authenticate({ 'username': config['PARSER']['Login'], 'password': config['PARSER']['Password'] })
  73.         await page.setJavaScriptEnabled(False)
  74.         # await page.setViewport({'width': 1200, 'height': 4000})
  75.        
  76.  
  77.         await page.setRequestInterception(True)
  78.  
  79.         async def intercept(request):
  80.             try:
  81.                 if any(request.resourceType == _ for _ in ('image', 'script')):
  82.                     await request.abort()
  83.                 else:
  84.                     await request.continue_()
  85.             except pyppeteer.errors.NetworkError as e:
  86.                 print(e)
  87.  
  88.         page.on('request', lambda req: asyncio.ensure_future(intercept(req)))
  89.        
  90.  
  91.         await page.goto('https://yandex.ru', {'timeout': 100000})
  92.         print("AFTER GOTO")
  93.         # await page.waitFor(4000)
  94.         # await page.waitForNavigation()
  95.         await page.focus('input[name=text]')
  96.         await page.keyboard.type(query),
  97.         await page.keyboard.press("Enter")
  98.         # await page.waitFor(4000)
  99.         await page.waitForNavigation({'timeout': 100000})
  100.         print(5)
  101.         html = await page.content()
  102.         d = pq(html)
  103.         captcha_input = d("input[name=rep]")
  104.  
  105.         # captcha_input = await page.evaluate("() => document.querySelector('input[name=rep]')")
  106.  
  107.         if len(captcha_input):
  108.             captcha_lnk = d('div.captcha__image img').attr('src')
  109.             # captcha_lnk = await page.evaluate("() => document.querySelector('div.captcha__image img').src")
  110.             print(captcha_lnk)
  111.             b64pic = get_as_base64(captcha_lnk)
  112.  
  113.             url = 'http://'+config['PARSER']['CapMonster']+'/createTask'
  114.             print(url)
  115.  
  116.             task = {
  117.                 "clientKey": "dce6bcbb1a728ea8d563de6d169a2057",
  118.                 "task": {
  119.                     "type": "ImageToTextTask",
  120.                     "body": b64pic,
  121.                     "phrase": False,
  122.                     "case": False,
  123.                     "numeric": False,
  124.                     "math": 0,
  125.                     "minLength": 0,
  126.                     "maxLength": 0
  127.                 }
  128.             }
  129.             print(6)
  130.  
  131.             r = requests.post(url, data=json.dumps(task))
  132.             res = r.json()
  133.             print(res)
  134.             taskId = res['taskId']
  135.  
  136.             # await page.waitFor(4000)
  137.  
  138.             url2 = 'http://'+config['PARSER']['CapMonster']+'/getTaskResult'
  139.  
  140.             task2 = {
  141.                 "clientKey": "dce6bcbb1a728ea8d563de6d169a2057",
  142.                 "taskId": taskId
  143.             }
  144.  
  145.             r = requests.post(url2, data=json.dumps(task2))
  146.             res = r.json()
  147.             print(res)
  148.             if 'solution' in res.keys():
  149.                 rep = res['solution']['text']
  150.             else:
  151.                 await page.close()
  152.                 await browser.close()
  153.                 return (query, False)
  154.             print(7)
  155.             await page.focus('input[name=rep]')
  156.             await page.keyboard.type(rep)
  157.             await page.keyboard.press("Enter")
  158.             # await page.waitFor(3000)
  159.             await page.waitForNavigation({'timeout': 100000})
  160.  
  161.             html = await page.content()
  162.             d = pq(html)
  163.             captcha_input = d("input[name=rep]")
  164.  
  165.             # captcha_input = await page.evaluate("() => document.querySelector('input[name=rep]')")
  166.             if len(captcha_input):
  167.                 print('wrong capcha')
  168.                 await page.close()
  169.                 await browser.close()
  170.                 # await tasks.add(loop.create_task(process(query)))
  171.                 return (query, False)
  172.  
  173.             else:
  174.                 html = await page.content()
  175.                 d = pq(html)
  176.                 page1 = d("li.serp-item")
  177.                 print('len', len(page1))
  178.  
  179.                 if not len(page1):
  180.                     await page.close()
  181.                     await browser.close()
  182.                     return (query, False)
  183.  
  184.                 sites = []
  185.                 for item in page1:
  186.                     d = pq(item)
  187.                     label = d("div.label")
  188.                    
  189.                     if len(label):
  190.                         if label.text() == 'реклама':
  191.                             site = d('a.link_theme_outer > b').text()
  192.                             if regex.search(r'\p{IsCyrillic}', site) is not None:
  193.                                 link = d('a.link_theme_outer').attr('href')
  194.                                 result = regex.search(r'market\.yandex\.ru', link)
  195.                                 if result is not None:
  196.                                     continue
  197.                                 print(query, link)
  198.                                 r = requests.get(link, allow_redirects=True)
  199.                                 content = r.text
  200.                                 result = regex.search(r'\;URL=\'.*\'', content)
  201.                                 if result is not None:
  202.                                     url = result.group(0)[6:-1]
  203.                                     site = urlparse(url).hostname
  204.                                     site = idna.decode(site)
  205.  
  206.  
  207.                             sites.append(site)
  208.  
  209.                 print(sites)
  210.  
  211.                 if not len(sites):
  212.                     await page.close()
  213.                     await browser.close()
  214.                     return (query, False)
  215.  
  216.                 print(8)
  217.                
  218.                 now = int(datetime.timestamp(datetime.now()))
  219.  
  220.                 async with aiosqlite.connect(os.path.join(BASEDIR, config['PARSER']['Database'])) as db:
  221.                    
  222.                     cursor = await db.execute("""INSERT INTO results (`text`, sites, updated, busy, file)  VALUES('{t}', '{s}', {u}, {b}, '{f}') ON CONFLICT(`text`)  DO UPDATE SET sites=excluded.sites, updated=excluded.updated, busy=excluded.busy, file=excluded.file""".format(t=query, s=json.dumps(sites), u=now, b=1, f='984.txt'))
  223.                     await db.commit()
  224.  
  225.                 print('DONE COMPLETE')
  226.                 # await page.screenshot({'path': query+'.png'})
  227.                 await page.close()
  228.                 await browser.close()
  229.                 return (query, True)
  230.  
  231.         else:
  232.             html = await page.content()
  233.             d = pq(html)
  234.             page1 = d("li.serp-item")
  235.             print('len', len(page1))
  236.  
  237.             if not len(page1):
  238.                 await page.close()
  239.                 await browser.close()
  240.                 return (query, False)
  241.  
  242.             print(9)
  243.  
  244.             sites = []
  245.             for item in page1:
  246.                 d = pq(item)
  247.                 label = d("div.label")
  248.                
  249.                 if len(label):
  250.                     if label.text() == 'реклама':
  251.                         site = d('a.link_theme_outer > b').text()
  252.                         if regex.search(r'\p{IsCyrillic}', site) is not None:
  253.                             link = d('a.link_theme_outer').attr('href')
  254.                             print(query, link)
  255.                             result = regex.search(r'market\.yandex\.ru', link)
  256.                             if result is not None:
  257.                                 continue
  258.                             r = requests.get(link, allow_redirects=True)
  259.                             content = r.text
  260.                             # print(query, content)
  261.                             result = regex.search(r'\;URL=\'.*\'', content)
  262.                             if result is not None:
  263.                                 url = result.group(0)[6:-1]
  264.                                 site = urlparse(url).hostname
  265.                                 site = idna.decode(site)
  266.  
  267.                         sites.append(site)
  268.  
  269.             print(sites)
  270.             if not len(sites):
  271.                 await page.close()
  272.                 await browser.close()
  273.                 return (query, False)
  274.  
  275.             now = int(datetime.timestamp(datetime.now()))
  276.  
  277.             async with aiosqlite.connect(os.path.join(BASEDIR, config['PARSER']['Database'])) as db:
  278.                
  279.                 cursor = await db.execute("""INSERT INTO results (`text`, sites, updated, busy, file)  VALUES('{t}', '{s}', {u}, {b}, '{f}') ON CONFLICT(`text`)  DO UPDATE SET sites=excluded.sites, updated=excluded.updated, busy=excluded.busy, file=excluded.file""".format(t=query, s=json.dumps(sites), u=now, b=1, f=config['PARSER']['Queries']))
  280.                
  281.                 await db.commit()
  282.        
  283.             print('DONE COMPLETE')
  284.             # await page.screenshot({'path': query+'.png'})
  285.             await page.close()
  286.             await browser.close()
  287.             return (query, True)
  288.  
  289.     except (pyppeteer.errors.TimeoutError, pyppeteer.errors.PageError, pyppeteer.errors.NetworkError, pyppeteer.errors.ElementHandleError) as e:
  290.         print(e)
  291.         await browser.close()
  292.         # await tasks.add(loop.create_task(process(query)))
  293.         return (query, False)
  294.  
  295. async def run(proxies):
  296.     tasks = set()
  297.  
  298.     no_concurrent = 5
  299.  
  300.     for query in queries:
  301.         if len(tasks) >= no_concurrent:
  302.             _done, tasks = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
  303.         proxy = random.choice(proxies)
  304.         task = asyncio.ensure_future(fetch(query, proxy))
  305.         tasks.add(task)
  306.  
  307.         while True:
  308.             try:
  309.                
  310.                 flag = True
  311.                
  312.                 print(2)
  313.  
  314.                 tmp = [task for task in tasks.copy() if task.done()]
  315.                 t = {}
  316.  
  317.                 for task in tmp:
  318.                     if task.result()[0] not in t.keys():
  319.                         t[task.result()[0]] = task
  320.                     elif task.result()[1]:
  321.                         t[task.result()[0]] = task
  322.  
  323.                 tmp = t.values()
  324.  
  325.                 for task in tmp:
  326.                     print(task.result())
  327.                     if not task.result()[1]:
  328.                         if len(tasks) >= no_concurrent:
  329.                             _done, tasks = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
  330.                         flag = False
  331.                         # tasks.add(loop.create_task(process(task.result()[0])))
  332.                         proxy = random.choice(proxies)
  333.                         task = asyncio.ensure_future(fetch(task.result()[0], proxy))
  334.                         tasks.add(task)
  335.  
  336.  
  337.                 if flag:
  338.                     break
  339.  
  340.             except ValueError as e:
  341.                 break
  342.  
  343.     responses = await asyncio.gather(*tasks)
  344.  
  345.     while True:
  346.         flag = True
  347.  
  348.         tmp = [task for task in tasks.copy() if task.done()]
  349.         t = {}
  350.  
  351.         print(3)
  352.  
  353.         for task in tmp:
  354.             if task.result()[0] not in t.keys():
  355.                 t[task.result()[0]] = task
  356.             elif task.result()[1]:
  357.                 t[task.result()[0]] = task
  358.  
  359.         tmp = t.values()
  360.  
  361.         for task in tmp:
  362.             print(task.result())
  363.             if not task.result()[1]:
  364.                 notdone = [task for task in tasks.copy() if not task.done()]
  365.                 if len(notdone) >= no_concurrent:
  366.                     _done, tasks = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
  367.                 flag = False
  368.                 print('3!!!!', task)
  369.                 proxy = random.choice(proxies)
  370.                 task = asyncio.ensure_future(fetch(task.result()[0], proxy))
  371.                 tasks.add(task)
  372.  
  373.         if flag:
  374.             break
  375.  
  376.     responses = await asyncio.gather(*tasks)
  377.  
  378.     async with aiosqlite.connect(os.path.join(BASEDIR, config['PARSER']['Database'])) as db:
  379.         db.row_factory = dict_factory
  380.         sql = "SELECT * FROM results"
  381.         cursor = await db.execute(sql)
  382.         rows = await cursor.fetchall()
  383.        
  384.         for i in range(len(rows)):
  385.             rows[i]['sites'] = json.loads(rows[i]['sites'])
  386.  
  387.  
  388. def yaparser():
  389.     while True:
  390.         loop = asyncio.new_event_loop()
  391.         asyncio.set_event_loop(asyncio.new_event_loop())
  392.         loop = asyncio.get_event_loop()
  393.         future = asyncio.ensure_future(run(proxies))
  394.         loop.run_until_complete(future)
  395.  
  396. def yaserver():
  397.     app = Flask(__name__)
  398.  
  399.     @app.route('/json', methods=['POST', 'GET'])
  400.     def do_json():
  401.         with sqlite3.connect(os.path.join(BASEDIR, config['PARSER']['Database'])) as db:
  402.             db.row_factory = dict_factory
  403.             sql = "SELECT `text`, sites, updated, busy, file AS id FROM results"
  404.             cursor = db.execute(sql)
  405.             rows = cursor.fetchall()
  406.            
  407.             for i in range(len(rows)):
  408.                 rows[i]['sites'] = json.loads(rows[i]['sites'])
  409.                 rows[i]['busy'] = bool(rows[i]['busy'])
  410.                 sites = rows[i]['sites']
  411.                 rows[i]['sites'] = []
  412.                 for j in range(len(sites)):
  413.                     rows[i]['sites'].append({'position': j, 'link': sites[j]})
  414.                
  415.  
  416.             response = app.response_class(
  417.                 response=json.dumps(rows),
  418.                 mimetype='application/json'
  419.             )
  420.            
  421.             return response
  422.  
  423.     @app.route('/text', methods=['POST', 'GET'])
  424.     def do_text():
  425.         with sqlite3.connect(os.path.join(BASEDIR, config['PARSER']['Database'])) as db:
  426.             db.row_factory = dict_factory
  427.             sql = "SELECT `text`, sites, updated, busy, file AS id FROM results"
  428.             cursor = db.execute(sql)
  429.             rows = cursor.fetchall()
  430.            
  431.             for i in range(len(rows)):
  432.                 rrows[i]['sites'] = json.loads(rows[i]['sites'])
  433.                 rows[i]['busy'] = bool(rows[i]['busy'])
  434.                 sites = rows[i]['sites']
  435.                 rows[i]['sites'] = []
  436.                 for j in range(len(sites)):
  437.                     rows[i]['sites'].append({'position': j, 'link': sites[j]})
  438.  
  439.             response = app.response_class(
  440.                 response=str(rows),
  441.                 mimetype='  text/html',
  442.             )
  443.  
  444.             response.headers["Content-Type"] = "text/html; charset=utf-8"
  445.            
  446.             return response
  447.  
  448.     app.secret_key = os.urandom(12)
  449.     app.run(debug=False,use_reloader=False, host='0.0.0.0', port=int(config['PARSER']['HTTP_port']))
  450.  
  451.  
  452. proc1 = None
  453. proc2 = None
  454.  
  455. def start():
  456.     current_process = psutil.Process()
  457.     children = current_process.children(recursive=True)
  458.     if not len(children):
  459.         proc1 = Process(target=yaserver, name='yaserver')
  460.         proc1.start()
  461.         proc2 = Process(target=yaparser, name='yaparser')
  462.         proc2.start()
  463.  
  464. def stop():
  465.     current_process = psutil.Process()
  466.     children = current_process.children(recursive=True)
  467.     for child in children:
  468.         print('Child pid {} terminate'.format(child.pid))
  469.         p = psutil.Process(child.pid)
  470.         p.terminate()
  471.  
  472. def on_closing():
  473.     stop()
  474.     window.destroy()
  475.  
  476. if __name__ == "__main__":
  477.     window = tk.Tk()
  478.     window.title("Yandex Parser")
  479.     # window.iconbitmap("ya.ico")
  480.     window.geometry('480x240')
  481.     arial36 = font.Font(family='Arial', size=12, weight=font.BOLD)
  482.     btn_run = Button(window, text="START", command=start, width=45, height=5, font=arial36)
  483.     btn_run.grid(row=1,column=2, padx=5, pady=5)
  484.     btn_stop = Button(window, text="STOP", command=stop, width=45, height=5, font=arial36)
  485.     btn_stop.grid(row=3,column=2, padx=5, pady=5)
  486.     window.protocol("WM_DELETE_WINDOW", on_closing)
  487.     window.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement