### Apache Airflow version

2.6.3

### What happened

A task instance's [log_url](https://github.com/apache/airflow/blob/2.6.3/airflow/models/taskinstance.py#L726) does not contain the full URL defined in [base_url](https://github.com/apache/airflow/blob/2.6.3/airflow/models/taskinstance.py#L729C9-L729C69).

### What you think should happen instead

The base_url may contain paths that should be acknowledged when build the log_url. 

The log_url is built with [urljoin](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urljoin). Due to how urljoin builds URLs, any existing paths are ignored leading to a faulty URL. 

### How to reproduce

This snippet showcases how urljoin ignores existing paths when building the url.

```
>>> from urllib.parse import urljoin
>>> 
>>> 
>>> urljoin(
...     "https://my.astronomer.run/path",
...     f"log?execution_date=test"
...     f"&task_id=wow"
...     f"&dag_id=super"
...     f"&map_index=-1",
... )
'https://eochgroup.astronomer.run/log?execution_date=test&task_id=wow&dag_id=super&map_index=-1'
```

### Operating System

n/a

### Versions of Apache Airflow Providers

_No response_

### Deployment

Astronomer

### Deployment details

_No response_

### Anything else

This was introduced by #31833.

A way to fix this can be to utilize [urlsplit](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlsplit) and [urlunsplit](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlunsplit) to account for existing paths.

```
from urllib.parse import urlsplit, urlunsplit

parts = urlsplit("https://my.astronomer.run/paths")
urlunsplit((
        parts.scheme,
        parts.netloc,
        f"{parts.path}/log",
        f"execution_date=test"
        f"&task_id=wow"
        f"&dag_id=super"
        f"&map_index=-1",
        ""
    )
)
```

Here is the fix in action.

```
>>> parts = urlsplit("https://my.astronomer.run/paths")
>>> urlunsplit((
...     parts.scheme,
...     parts.netloc,
...     f"{parts.path}/log",
...     f"execution_date=test"
...     f"&task_id=wow"
...     f"&dag_id=super"
...     f"&map_index=-1",
...     ''))
'https://my.astronomer.run/paths/log?execution_date=test&task_id=wow&dag_id=super&map_index=-1'
>>>
>>> parts = urlsplit("https://my.astronomer.run/paths/test")
>>> urlunsplit((
...     parts.scheme,
...     parts.netloc,
...     f"{parts.path}/log",
...     f"execution_date=test"
...     f"&task_id=wow"
...     f"&dag_id=super"
...     f"&map_index=-1",
...     ''))
'https://my.astronomer.run/paths/test/log?execution_date=test&task_id=wow&dag_id=super&map_index=-1'
```

### Are you willing to submit PR?

- [ ] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

tis: list[TaskInstance],
    session: Session,
    activate_dag_runs: None = None,
    dag: DAG | None = None,
    dag_run_state: DagRunState | Literal[False] = DagRunState.QUEUED,
) -> None:
    """
    Clears a set of task instances, but makes sure the running ones get killed.
    Also sets Dagrun's `state` to QUEUED and `start_date` to the time of execution.
    But only for finished DRs (SUCCESS and FAILED).
    Doesn't clear DR's `state` and `start_date`for running
    DRs (QUEUED and RUNNING) because clearing the state for already
    running DR is redundant and clearing `start_date` affects DR's duration.
    :param tis: a list of task instances
    :param session: current session
    :param dag_run_state: state to set finished DagRuns to.
        If set to False, DagRuns state will not be changed.
    :param dag: DAG object
    :param activate_dag_runs: Deprecated parameter, do not pass
    """
    job_ids = []
    
    task_id_by_key: dict[str, dict[str, dict[int, dict[int, set[str]]]]] = defaultdict(
        lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(set)))
    )
    dag_bag = DagBag(read_dags_from_db=True)
    for ti in tis:
        if ti.state == TaskInstanceState.RUNNING:
            if ti.job_id: