Stock product and lot duplicate finder
Avoid similar variable names
There's line.product_id.id, line_id and line.id. This is very confusing. Try to avoid having variable names that are too close to each other.
Simplifying the code
You can indeed simplify the code somewhat. First, you want to find out if there are multiple lines that reference the same product. To do that, you want to have a dict that maps from product IDs to a list of lines. The easiest way to do this is to use a defaultdict(list):
from collections import defaultdict

def check_for_duplicates(self):
    product_lines = defaultdict(list)

    # Build a map of which lines reference which products
    for line in picking.move_lines:
        product_lines[line.product_id.id].append(line.id)

Then you can go over that map to check if any product occurs on more than one line:
    # Find duplicates
    for product, lines in product_lines.items():
        if len(lines) &gt; 1:
            # Report lines with duplicate products here
            ...

I'm not sure how to improve on the part that checks for duplicate lots, I don't know what type self.env[...] is and what the browse() function does, but perhaps the above code will help you simplify that as well.