Use expression:
(?<=>)[^<:]+(?=:?<)
(?<=>) Positive lookbehind for >.
[^<:]+ Match anything other than < or :.
(?=:?<) Positive lookahead for optional colon :, and <.
You can try the expression live here.
In Python:
import re
first_string = '<h4 id="Foobar:">Foobar:</h4>'
second_string = '<h1 id="Monty">Python<a href="https://..."></a></h1>'
print(re.findall(r'(?<=>)[^<:]+(?=:?<)',first_string)[0])
print(re.findall(r'(?<=>)[^<:]+(?=:?<)',second_string)[0])
Prints:
Foobar
Python
Alternatively you could use expression:
(?<=>)[a-zA-Z]+(?=\W*<)
(?<=>) Positive lookbehind for >.
[a-zA-Z]+ Lower and upper case letters.
(?=\W*<) Positive lookahead for any non word characters followed by <.
You can test this expression here.
print(re.findall(r'(?<=>)[a-zA-Z]+(?=\W*<)',first_string)[0])
print(re.findall(r'(?<=>)[a-zA-Z]+(?=\W*<)',second_string)[0])
Prints:
Foobar
Python