Wikidata:Pywikibot - Python 3 Tutorial/Merging items

If two Item are duplicates they can be merged. It is important that the bot makes sure that the merge is really necessary. Otherwise it will merge items that is not necessarily duplicates .

Merge item into another can be done with this code:

# -*- coding: utf-8  -*-
import pywikibot
"""
Merge item into another and creates a redirect
"""

class Merger:
    # GNU General Public License v2.0 @ matejsuchanek
    # https://github.com/matejsuchanek/pywikibot-scripts/blob/master/merger.py
    
    no_conflict_props = {'P17', 'P21', 'P105', 'P170', 'P171', 'P225', 'P271',
                         'P296', 'P495', 'P569', 'P570', 'P734', 'P856'}
    no_conflict_trees = {
        'P19': 'P131',
        'P31': 'P279',
        'P131': 'P131',
        'P279': 'P279',
    }
    no_conflict_types = ['external-id']
    
    def can_merge(cls, item1, item2, quick=True):
        props = list(cls.no_conflict_props)
        if quick:
            props.extend(cls.no_conflict_trees.keys())

        for prop in props:
            item1.get()
            data1 = item1.claims.get(prop, [])
            if not data1:
                continue
            item2.get()
            data2 = item2.claims.get(prop, [])
            if not data2:
                continue
            if cls._conflicts(data1, data2):
                return False

        key = lambda claims: claims[0].id
        for dtype in cls.no_conflict_types:
            callback = lambda claims: claims[0].type == dtype
            item1.get()
            keys1 = set(map(key, filter(callback, item1.claims.values())))
            if not keys1:
                continue
            item2.get()
            keys2 = set(map(key, filter(callback, item2.claims.values())))
            if not keys2:
                continue
            for prop in keys1 & keys2:
                if cls._conflicts(item1.claims[prop], item2.claims[prop]):
                    return False

        if not quick:
            for prop in cls.no_conflict_trees:
                item1.get()
                data1 = item1.claims.get(prop, [])
                if not data1:
                    continue
                item2.get()
                data2 = item2.claims.get(prop, [])
                if not data2:
                    continue
                if not cls._same_tree(cls.no_conflict_trees[prop], data1, data2):
                    return False

        return True


site = pywikibot.Site("test", "wikidata")
repo = site.data_repository()
merger_helper = Merger()

item = pywikibot.ItemPage(repo, "Q92107")
item2 = pywikibot.ItemPage(repo, "Q179725")

if merger_helper.can_merge(item, item2):
    item.mergeInto(item2, summary="Merge Q92107 into Q179725 and creates a redirect")

The function mergeInto() is used for merging items. In this example the itemPage variable item (Q92107) is merged into item2 (Q179725).

There is a helper class used to check for conflicts that has to be solved before merge. Take a look at matejsuchanek/pywikibot-scripts for a more advanced script for marging items.