Py3 ebay-scraper - Project I need cheap GPU
There are multiple things to improve, let's try to categorize them.

Code Style


there is a number of PEP8 code style violations, specifically:


documentations strings need to be enclosed into triple double quotes, start with a capital letter and end with a dot (reference)
group imports properly

handling a bare exception with except: is considered a bad practice
when you check for a substring to be present in a string, you can use not in, e.g. not 'shipping' in li.text.lower() can be replaced with a more readable:

'shipping' not in li.text.lower()

I would also improve the way you format the search URL, extracting the base url as a constant and using str.format() to insert keywords into the URL:

BASE_URL_TEMPLATE = 'https://www.ebay.com/sch/i.html?_from=R40&amp;_trksid=m570.l1313&amp;_nkw={keywords}&amp;_sacat=0'


def make_search_string(keywords):
    """Constructs a search products string."""
    return BASE_URL_TEMPLATE.format(keywords='+'.join(keywords))



Web-Scraping and HTML Parsing


if you would switch to requests instead of urllib, you then can seriously improve on the performance of making the requests by re-using a session:


  ..if you're making several requests to the same host, the underlying TCP connection will be reused, which can result in a significant performance increase.

lxml if used instead of html.parser can provide an HTML parsing performance boost as well
see if using a SoupStrainer to focus your HTML parser on the desired part of the HTML tree only is also applicable in your scenario. It can further speed up the HTML parsing step  
using a LBYL approach inside the find_next_page would be a bit more readable and concise:

def find_next_page(soup):
    """
    Finds next page.

    Returns:
        Next page link if exists
        None if next page does not exists
    """
    next_page_link = soup.select_one('a.next')
    return next_page_link['href'] if next_page_link else None

scrape_page() function is overly complicated. For instance, there is a single element with id="ListViewInner" on the page and it does not require a loop to locate this element. And, you can do better in locating elements on the page:

def scrape_page(soup, index):
    """
    Scrapes page for products and save them as a dictionary.

    Returns:
        A dictionary of products
    """
    products = {}

    for produce_index, item in enumerate(soup.select('#ResultSetItems li'), index):
        title = item.select_one('a.vip')
        price = item.select_one(".prc")
        shipping_price = item.select_one('.ship')

        products[produce_index] = {
            'Title': title.find(text=True, recursive=False) if title else None,
            'Price': price.get_text(strip=True) if price else None,
            'Shipping': shipping_price.get_text(strip=True).split()[0] if shipping_price else None
        }

    return products, produce_index


(not tested)


Also note the use of enumerate() for better handling enumeration (thanks @graipher for the idea).