Using Supertool to import Attributes and URLs - An example

I recently grafted a section on to my Family Tree that was exported from Ancestry. As part of this process, I wanted to add an internet link to each person that links directly back to the source person at Ancestry and Ancestry Library Edition. I also wanted to add the TreeID and PersonID variables from the URL as Attributes to each person.

Below is the process I followed to add the Attributes and URLs using the SuperTool. I was able to do all this using the SuperTool using Gramps that is installed and running on the Windows Subsystem for Linux (wsl). I don’t think this process will work with Gramps-AIO (Sorry). I hope this process can assist others hoping to do similar imports.

Create Spreadsheet
Though I performed a GEDCOM import from Ancestry to Gramps, the urls found the source citations did not have a PersonID that would work for my purposes.

I was able to get a list of useable URLs from Ancestry Library Edition. (on the tree view look for an option to list of members of a tree). I created a CSV file of the URLs that I needed via copy and paste. I added the gramps_id column and manually populated it by comparing the list to my Gramps database. (This is the most time-consuming part of this process)

My csv file looks like this:

gramps_id,Name,AncestryTreeURL,Birth,Death
I00959,"Jackson, Charlotte Mary",https://www.ancestrylibrary.ca/family-tree/person/tree/26996426/person/280178700488,"abt 1849 - Islington, Middlesex, England",-
I00022,"Jackson, Clifford Henders",https://www.ancestrylibrary.ca/family-tree/person/tree/26996426/person/1968626141,"21 Jul 1904 - York, Ontario, Canada","05 JAN 1954 - Toronto, Ontario, Canada"
I00011,"Jackson, Dorothy Bessie",https://www.ancestrylibrary.ca/family-tree/person/tree/26996426/person/1968626143,"12 Nov 1899 - York, Ontario, Canada",-
I00794,"JACKSON, Edward",https://www.ancestrylibrary.ca/family-tree/person/tree/26996426/person/1968626144,"abt 1824 - St Clements, Middlesex, England",1861 - Queensland

The SuperTool script will extract the Tree ID and Person ID from the URL.

https://www.ancestrylibrary.ca/family-tree/person/tree/26996426/person/1968626144

Install Pandas on my computer (https://pandas.pydata.org/)
I used pandas to load the csv and search the csv. This is the reason, I don’t think this script won’t work with Gramps-AIO.

pip install pandas

Install SuperTool
The Wiki has instructions on this: Addon:Isotammi addons - Gramps

Load and Run the SuperTool Script
I have left the script on Github so it can be updated, as needed, after this discussion topic closes.

[Gramps SuperTool script file]
version=1

[title]
Import Ancestry URL and ID numbers

[category]
People

[initial_statements]
#
# import classes
#
import pandas as pd
from urllib.parse import urlparse, parse_qs, unquote
from pathlib import PurePosixPath
from gramps.gen.lib import Attribute, AttributeType, Person, Url, UrlType

#
# Create objects.  In this case, we are adding 2 attributes and 2 urls to each
# person.
#

attr = Attribute()
attr1 = Attribute()

attr_type = AttributeType()
attr1_type = AttributeType()

url_type = UrlType()
url = Url()

url1_type = UrlType()
url1 = Url()

#
# read the source csv file into a dataframe
#
df = pd.read_csv('/mnt/c/Users/Public/Documents/Genealogy-Gramps/SuperTool-Scripts/AncestryLibraryUntitled1a.csv')

#
# Parse the url and create a new column with the unique IDs.  
# URL structure has IDs in the path https://www.ancestrylibrary.ca/family-tree/person/tree/26996426/person/1968625748
#
df['AncestryLibrary_TreeID'] = df.apply(lambda row: PurePosixPath(unquote(urlparse(row.AncestryTreeURL).path)).parts[4], axis=1)
df['AncestryLibrary_PersonID'] = df.apply(lambda row: PurePosixPath(unquote(urlparse(row.AncestryTreeURL).path)).parts[6], axis=1)

[statements]
#
# search for the row in the dataframe by gramps_id.  
#
try: 
    ancestry_row = df.loc[df["gramps_id"] == gramps_id, ('AncestryLibrary_TreeID', 'AncestryLibrary_PersonID','AncestryTreeURL')]

    #
    # Convert the values to a string (without the row number) and assign to variables.
    #
    AncestryLibrary_TreeID = ancestry_row["AncestryLibrary_TreeID"].to_string(index=False)
    Person_ID = ancestry_row["AncestryLibrary_PersonID"].to_string(index=False)
    AncestryTreeURL = ancestry_row["AncestryTreeURL"].to_string(index=False)
    objAncestryTreeURL = ancestry_row["AncestryTreeURL"]

    #
    # Test to make sure we have an result to parse.
    #
    if objAncestryTreeURL.size:

        #
        # set the attributes and urls and add to the person.
        #
        attr_type.set('Ancestry_Jackson_Tree_PersonID')
        attr.set_type(attr_type)
        attr.set_value(Person_ID)
        person.add_attribute(attr)

        attr1_type.set('Ancestry_Jackson_Tree_TreeID')
        attr1.set_type(attr1_type)
        attr1.set_value(AncestryLibrary_TreeID)
        person.add_attribute(attr1)

        url_type.set('AncestryLibrary_Jackson_Tree')
        url.set_type(url_type)
        url.set_path(AncestryTreeURL)
        person.add_url(url)

        url1_type.set('Ancestry_Jackson-Tree ($)')
        url1.set_type(url1_type)
        url1.set_path(AncestryTreeURL.replace('ancestrylibrary','ancestry'))
        person.add_url(url1)

except:
    print('no value found')

[filter]

[expressions]

[scope]
all

[unwind_lists]
True

[commit_changes]
True

[summary_only]
True
2 Likes

I’d tried to use gramps from WSL (Windows Subsystem for Linux) but it didn’t work well (windowing issues as I remember). Do you use it always from WSL or just for this then regulary from windows ?

I always use Gramps on WSL. I’m using x410 (https://x410.dev/cookbook/wsl/using-x410-with-wsl2/). I found it works better than VcXsrv. With VcXsrv I did observe windowing issues.

If you want to discuss more gramps on wsl, let’s open up a new topic.

1 Like

Perplexity AI suggests using the csv module because it is part of the Python standard library:

import csv

with open('data.csv', 'r') as file:
    csv_reader = csv.reader(file)
    
    for row in csv_reader:
        # Process each row
        print(row)

Alternatively, use the csv.DictReader() class to read the CSV file as a dictionary, using the first row as keys:

import csv

with open('data.csv', 'r') as file:
    csv_reader = csv.DictReader(file)
    
    for row in csv_reader:
        # Process each row as a dictionary
        print(row)