获取按钮和窗体的黑色屏幕截图

2024-04-28 08:55:18 发布

您现在位置:Python中文网/ 问答频道 /正文

这段代码的问题是,我用一个屏幕截图(如Home、about、menu)获得了我想要的文本,所有这些截图都带有裁剪出来的屏幕截图,但这段代码在按钮、表单和其他一些操作上显示了一个黑色屏幕截图。我需要表单图像和按钮图像与裁剪和其他屏幕截图,是黑色的。但似乎找不到问题出在哪里,为什么只在按钮和窗体上显示黑色屏幕截图

import boto3, os
from botocore.exceptions import ClientError
from io import BytesIO

from PIL import Image
import time
import os, glob
from bs4 import BeautifulSoup
from IPython.display import clear_output
import json
from shutil import copyfile
import numpy as np

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import uuid

import json
from urllib.request import Request, urlopen
import requests
import re
import itertools
from bs4 import BeautifulSoup
#import openai
from multiprocessing.pool import ThreadPool




def xpath_soup(element):
    # type: (typing.Union[bs4.element.Tag, bs4.element.NavigableString]) -> str
    """
    Generate xpath from BeautifulSoup4 element.
    :param element: BeautifulSoup4 element.
    :type element: bs4.element.Tag or bs4.element.NavigableString
    :return: xpath as string
    :rtype: str
    Usage
    -----
    >>> import bs4
    >>> html = (
    ...     '<html><head><title>title</title></head>'
    ...     '<body><p>p <i>1</i></p><p>p <i>2</i></p></body></html>'
    ...     )
    >>> soup = bs4.BeautifulSoup(html, 'html.parser')
    >>> xpath_soup(soup.html.body.p.i)
    '/html/body/p[1]/i'
    >>> import bs4
    >>> xml = '<doc><elm/><elm/></doc>'
    >>> soup = bs4.BeautifulSoup(xml, 'lxml-xml')
    >>> xpath_soup(soup.doc.elm.next_sibling)
    '/doc/elm[2]'
    """
    components = []
    child = element if element.name else element.parent
    for parent in child.parents:  # type: bs4.element.Tag
        siblings = parent.find_all(child.name, recursive=False)
        components.append(
            child.name if 1 == len(siblings) else '%s[%d]' % (
                child.name,
                next(i for i, s in enumerate(siblings, 1) if s is child)
            )
        )
        child = parent
    components.reverse()
    return '/%s' % '/'.join(components)


def save_screenshot(driver: webdriver.Chrome, path: str = './screenshot.png') -> None:
    # Ref: https://stackoverflow.com/a/52572919/
    original_size = driver.get_window_size()
    required_width = driver.execute_script('return document.body.parentNode.scrollWidth')
    required_height = driver.execute_script('return document.body.parentNode.scrollHeight')
    driver.set_window_size(required_width, required_height)
    png = driver.get_screenshot_as_png()
    driver.save_screenshot(path)  # has scrollbar
    # driver.find_element_by_tag_name('body').screenshot(path)  # avoids scrollbar
    # driver.set_window_size(original_size['width'], original_size['height'])
    return driver, png


def get_images(driver, elements, im, verbose=0):
    new_elements = []
    for idx in range(len(elements)):
        xpath = elements[idx]['xpath']
        text = elements[idx]['originalText']

        try:
            element = driver.find_element_by_xpath(xpath)
            if element.is_displayed():
                location = element.location
                size = element.size

                cropped_im = im.crop(
                    (
                        location['x'], location['y'],
                        location['x'] + size['width'], location['y'] + size['height'])

                )
            
            
                if verbose: print('xpath: ', xpath)
                if verbose: print('text: ', text)
                # elements[idx]['image'] = cropped_im
                _, image_url = pil_to_s3(cropped_im)
                elements[idx]['jpeg_path'] = image_url
                # new_elements[idx]['image'] = cropped_im
                if verbose: display(cropped_im)
                if verbose: print()
                if verbose: print()
                if verbose: print()

                new_elements.append(elements[idx])
            else:
                if verbose: print(f"element {xpath} is not displayed")
                pass
        except:
            pass
    return new_elements


def pil_to_s3(pil_image):
    bucket_name = 'ekkelai-kevins'
    key = str(uuid.uuid4()) + '.jpg'

    pil_image = pil_image.convert('RGB')
    buffer = BytesIO()
    pil_image.save(buffer, "JPEG")
    buffer.seek(0)  # rewind pointer back to start
    response = client.put_object(
        ACL='public-read',
        Bucket=bucket_name,
        Key=key,
        Body=buffer,
        ContentType='image/jpeg',
    )
    image_url = "https://{0}.s3.amazonaws.com/{1}".format(bucket_name, key)
    return response, image_url


# text = "Making AI Simple For You."

def lambda_handler(event_jsonified, context):
    outputs = {}
    try:
        event = json.loads(event_jsonified['body'])
        url = event['url']
        tag_types = ['h1', 'h2']
        req = Request(url)  # headers={'User-Agent': 'Mozilla/5.0'}
        html = urlopen(req).read()
        soup = BeautifulSoup(html, 'html')  # lxml

        outputs['gpt3_text'] = get_options([tag_types], soup)
        outputs['conversion_elements'] = [
            {'xpath': xpath_soup(element), 'tagType': element.name, 'originalText': element.text} for element in
            soup.find_all(['input'])]

        return {
            'statusCode': 200,
            'headers': {
                'Access-Control-Allow-Headers': 'Content-Type',
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Methods': '*'
            },
            'body': json.dumps(outputs),
        }

    except Exception as e:
        outputs['error'] = str(e)
        # outputs['error'] = traceback.format_exc()
        return {
            'statusCode': 200,
            'headers': {
                'Access-Control-Allow-Headers': 'Content-Type',
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Methods': '*'
            },
            'body': json.dumps(outputs)
        }


#########################################################################
def create_phrases(text):
    openai.api_key = ""
    response = openai.Completion.create(
        engine="davinci-instruct-beta",
        prompt=text,
        temperature=0.65,
        max_tokens=60,
        top_p=1,
        frequency_penalty=0.2,
        presence_penalty=0.0,
        stop=["\n\n"]
    )
    return response['choices'][0]['text']


# ========================================================================
def get_phrases(text):
    # outputs = []
    # while len(outputs) < 3:
    #     inp_text = f'Rephrase the following in three ways:\n""""""\n{text}\n""""""\n1.'
    #     out = create_phrases(inp_text)
    #     out = out.strip().replace('"', '').replace('\n\n', '\n')
    #     outputs = out.split('\n')
    # outputs = outputs[0:3]

    # '''i am removing digits from selected three outputs'''
    # for i in range(len(outputs)):
    #     digits = re.findall(r'[0-9]+\.', outputs[i])
    #     if len(digits) > 0:
    #         for j in range(len(digits)):
    #             outputs[i] = outputs[i].replace(digits[j], '')
    outputs = ['Option 1', 'Option 2', 'Option 3']
    return outputs


#########################################################################

def get_options(tag_types, soup):
    data = ''
    for tag_type in tag_types:
        all_elements = soup.find_all(tag_type)
        print(f"total elements: {len(all_elements)}")
        print(f"elements for tag type: {tag_type}: {len(all_elements)}")
        if len(all_elements)<1:
            continue
        pool = ThreadPool(len(all_elements))

        all_txt_elements, all_xpaths, all_tag_types = [], [], []
        for element in all_elements:
            text = element.getText()
            tag_type = element.name

            if text != None and text != '':
                xpath = xpath_soup(element)
            else:
                continue

            all_txt_elements.append(text)
            all_xpaths.append(xpath)
            all_tag_types.append(tag_type)

        # print('lengths: ', len(all_txt_elements), len(all_xpaths), len(all_tag_types))
        data = pool.starmap(process_element, zip(all_txt_elements, all_xpaths, all_tag_types))
        pool.close()
    return data


def xpath_soup(element):
    # type: (typing.Union[bs4.element.Tag, bs4.element.NavigableString]) -> str
    """
    Generate xpath from BeautifulSoup4 element.
    :param element: BeautifulSoup4 element.
    :type element: bs4.element.Tag or bs4.element.NavigableString
    :return: xpath as string
    :rtype: str
    Usage
    -----
    >>> import bs4
    >>> html = (
    ...     '<html><head><title>title</title></head>'
    ...     '<body><p>p <i>1</i></p><p>p <i>2</i></p></body></html>'
    ...     )
    >>> soup = bs4.BeautifulSoup(html, 'html.parser')
    >>> xpath_soup(soup.html.body.p.i)
    '/html/body/p[1]/i'
    >>> import bs4
    >>> xml = '<doc><elm/><elm/></doc>'
    >>> soup = bs4.BeautifulSoup(xml, 'lxml-xml')
    >>> xpath_soup(soup.doc.elm.next_sibling)
    '/doc/elm[2]'
    """
    components = []
    child = element if element.name else element.parent
    for parent in child.parents:  # type: bs4.element.Tag
        siblings = parent.find_all(child.name, recursive=False)
        components.append(
            child.name if 1 == len(siblings) else '%s[%d]' % (
                child.name,
                next(i for i, s in enumerate(siblings, 1) if s is child)
            )
        )
        child = parent
    components.reverse()
    return '/%s' % '/'.join(components)


def process_element(text, xpath, tag_type):
    options = get_phrases(text)

    return {
        'xpath': xpath,
        'tagType': tag_type,
        'originalText': text,
        'options': options
    }
tag_types = ['h1', 'h2']
outputs = {}
# json_data = request.get_json()
# url = json_data['url']
url = "http://stevens.ekkel.ai"
print("*"*100)
print(url)
print("*"*100)

from selenium.webdriver.chrome.options import Options
# url = "https://www.tourism.net.nz/attractions-and-activities#tab-categories"
chrome_options = Options()
#chrome_options.add_argument('--headless')
#chrome_options.add_argument('--no-sandbox')
#chrome_options.add_argument('--disable-gpu')
#chrome_options.add_argument('--window-size=1280x1696')
#chrome_options.add_argument('--user-data-dir=/tmp/user-data')
#chrome_options.add_argument('--hide-scrollbars')
#chrome_options.add_argument('--enable-logging')
#chrome_options.add_argument('--log-level=0')
#chrome_options.add_argument('--v=99')
#chrome_options.add_argument('--single-process')
#chrome_options.add_argument('--data-path=/tmp/data-path')
#chrome_options.add_argument('--ignore-certificate-errors')
#chrome_options.add_argument('--homedir=/tmp')
#chrome_options.add_argument('--disk-cache-dir=/tmp/cache-dir')
#chrome_options.add_argument('user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36')

# chrome_options.add_argument('--start-maximized')
driver = webdriver.Chrome(executable_path=r'./chromedriver.exe', chrome_options=chrome_options)
driver.get(url)
time.sleep(2)
html = driver.page_source
soup = BeautifulSoup(html, 'html')  # lxml
# print(soup)
# raise Exception
# get eligible elements
outputs['gpt3_text'] = get_options([tag_types], soup)
outputs['conversion_elements'] = [
    {'xpath': xpath_soup(element), 'tagType': element.name, 'originalText': element.text} for element in
    soup.find_all(['a', 'button', 'form'])]

# get full screenshot
driver, png = save_screenshot(driver, path='./screenshot.png')
im = Image.open(BytesIO(png))  # uses PIL library to open image in memory

# get and save element screenshots
outputs['conversion_elements'] = get_images(driver, outputs['conversion_elements'], im)
outputs['gpt3_text'] = get_images(driver, outputs['gpt3_text'], im)

# quit driver and cleanup
driver.quit()
print("done")


Tags: textfromimporthtmltagdriverelementselement