Repository: yt-dlp
Issue: `get_element_by_attribute` doesn't work with uppercased html tags
Labels: bug,core:extractor

### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I *intentionally* remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting a bug unrelated to a specific site
- [X] I've verified that I have **updated yt-dlp to nightly or master** ([update instructions](https://github.com/yt-dlp/yt-dlp#update-channels))
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#video-url-contains-an-ampersand--and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766) and the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)

### Provide a description that is worded well enough to be understood

Examples:

```py
from ..utils import (
    get_element_by_attribute,
    get_element_by_id,
    get_element_by_class,
)

# doesn't work
get_element_by_attribute('id', 'test', '<SPAN id="test">test</SPAN>')
get_element_by_id('test', '<SPAN id="test">test</SPAN>')
get_element_by_class('test', '<SPAN class="test">test</SPAN>')

# works fine
get_element_by_attribute('id', 'test', '<span id="test">test</span>')
get_element_by_id('test', '<span id="test">test</span>')
get_element_by_class('test', '<span class="test">test</span>')
```

They return this error:

```bash
ERROR: parser did not match opening SPAN tag
```

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [ ] If using API, add `'verbose': True` to `YoutubeDL` params instead
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
$ ./yt-dlp.cmd -v https://live.erinn.biz/live.php?h675134569
[debug] Command-line config: ['-v', 'https://live.erinn.biz/live.php?h675134569']
[debug] Encodings: locale cp1251, fs utf-8, pref cp1251, out utf-8, error utf-8, screen utf-8 
[debug] yt-dlp version stable@2023.11.16 from yt-dlp/yt-dlp [24f827875] (source) 
[debug] Lazy loading extractors is disabled
[debug] Git HEAD: ca4bd6746
[debug] Python 3.12.1 (CPython AMD64 64bit) - Windows-10-10.0.19044-SP0 (OpenSSL 3.0.11 19 Sep 2023) 
[debug] exe versions: ffmpeg 2023-12-28-git-c1340f3439-full_build-www.gyan.dev (setts), ffprobe 2023-12-28-git-c1340f3439-full_build-www.gyan.dev 
[debug] Optional libraries: sqlite3-3.43.1 
[debug] Proxy map: {}
[debug] Request Handlers: urllib
[debug] Loaded 1799 extractors 
[KukuluLive] Extracting URL: https://live.erinn.biz/live.php?h675134569 
ERROR: parser did not match opening SPAN tag 
Traceback (most recent call last):
  File "D:\Documents\yt-dlp\yt_dlp\YoutubeDL.py", line 1581, in wrapper
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Documents\yt-dlp\yt_dlp\YoutubeDL.py", line 1716, in __extract_info
    ie_result = ie.extract(url)
                ^^^^^^^^^^^^^^^
  File "D:\Documents\yt-dlp\yt_dlp\extractor\common.py", line 718, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Documents\yt-dlp\yt_dlp\extractor\kukululive.py", line 65, in _real_extract
    get_element_by_id('test', '<SPAN id="test">test</SPAN>')
  File "D:\Documents\yt-dlp\yt_dlp\utils\_utils.py", line 291, in get_element_by_id
    return get_element_by_attribute('id', id, html, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Documents\yt-dlp\yt_dlp\utils\_utils.py", line 312, in get_element_by_attribute
    retval = get_elements_by_attribute(attribute, value, html, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Documents\yt-dlp\yt_dlp\utils\_utils.py", line 337, in get_elements_by_attribute
    return [content for content, _ in get_elements_text_and_html_by_attribute(*args, **kwargs)]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Documents\yt-dlp\yt_dlp\utils\_utils.py", line 364, in get_elements_text_and_html_by_attribute
    content, whole = get_element_text_and_html_by_tag(m.group('tag'), html[m.start():])
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Documents\yt-dlp\yt_dlp\utils\_utils.py", line 434, in get_element_text_and_html_by_tag
    raise compat_HTMLParseError(f'parser did not match opening {tag} tag')
yt_dlp.compat.compat_HTMLParseError: parser did not match opening SPAN tag
```