Определите URL и добавьте метки привязки, используя BeautifulSoup - PullRequest
0 голосов
/ 18 мая 2018

Я анализирую HTML, используя BeautifulSoup.Учитывая следующий HTML:

<!DOCTYPE html>
<html>
    <body>
        <p>An absolute URL: https://www.w3schools.com</p>
    </body>
</html>

Я хочу преобразовать его в:

<!DOCTYPE html>
<html>
    <body>
        <p>An absolute URL: <a href="https://www.w3schools.com" target="_blank">https://www.w3schools.com</a></p>
    </body>
</html>

Код, написанный до сих пор:

def detect_urls_and_update_target(self, root): //root is the soup object
        for tag in root.find_all(True):
            if tag.name == 'a':
                if not tag.has_attr('target'):
                    tag.attrs['target'] = '_blank'
            elif tag.string is not None:
                  for url in re.findall(self.url_regex, tag.string): //regex which detects URLS which works
                      new_tag = root.new_tag("a", href=url, target="_blank")
                      new_tag.string = url
                      tag.append(new_tag)

Это добавляет необходимый тег привязки, ноЯ не могу понять, как удалить исходный URL из тега.

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Вы можете использовать BeautifulSoup для восстановления родительского содержимого следующим образом:

from bs4 import BeautifulSoup
import re

html = """<!DOCTYPE html>
<html>
    <body>
        <p>An absolute URL: https://www.w3schools.com</p>
        <p>Another link: /11128107/opredelite-url-i-dobavte-metki-privyazki-ispolzuya-beautifulsoup</p>
        <div><div>some div</div>Hello world from https://www.google.com</div>
    </body>
</html>"""

soup = BeautifulSoup(html, "html.parser")
re_url = re.compile(r'(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)')

for tag in soup.find_all(text=True):
    tags = []
    url = False

    for t in re_url.split(tag.string):
        if re_url.match(t):
            a = soup.new_tag("a", href=t, target='_blank')
            a.string = t
            tags.append(a)
            url = True
        else:
            tags.append(t)

    if url:
        for t in tags:
            tag.insert_before(t)
        tag.extract()

print(soup)    
print()

Это будет отображать следующий вывод:

<!DOCTYPE html>

<html>
<body>
<p>An absolute URL: <a href="https://www.w3schools.com" target="_blank">https://www.w3schools.com</a></p>
<p>Another link: <a href="/11128107/opredelite-url-i-dobavte-metki-privyazki-ispolzuya-beautifulsoup" target="_blank">/11128107/opredelite-url-i-dobavte-metki-privyazki-ispolzuya-beautifulsoup</a></p>
<div><div>some div</div>Hello world from <a href="https://www.google.com" target="_blank">https://www.google.com</a></div>
</body>
</html>

Это работает, сначала разбивая любые теги, содержащие текст, используярегулярное выражение для поиска любого URL.Для каждой записи, если это URL, замените его в списке новым тегом привязки.Если URL не найдены, оставьте тег в покое.Затем вставьте каждый список обновленных тегов перед существующим тегом, а затем удалите существующий тег.


Чтобы пропустить любые URL-адреса в DOCTYPE, find_all() можно изменить следующим образом:

from bs4 import BeautifulSoup, Doctype

...

for tag in soup.find_all(string=lambda text: not isinstance(text, Doctype)):
0 голосов
/ 18 мая 2018

Вы можете использовать re.sub с декоратором для переноса любых вхождений URL в тело тега с предоставленными параметрами:

import re
def format_hrefs(tags=['p'], _target='blank', a_class=''):
   def outer(f):
     def format_url(url):
        _start = re.sub('https*://www\.[\w\W]+\.\w{3}', '{}', url)
        return _start.format(*['<a href="{}" _target="{}" class="{}">{}</a>'.format(i, _target, a_class, i) for i in re.findall('https*://www\.\w+\.\w{3}', url)])
     def wrapper():
        url = f()
        _format = re.sub('|'.join('(?<=\<'+i+'\>)[\w\W]+(?=\</'+i+'\>)' for i in tags), '{}', html)
        _text = re.findall('|'.join('(?<=\<'+i+'\>)[\w\W]+(?=\</'+i+'\>)' for i in tags), html)
        return _format.format(*[format_url(i) for i in _text])
     return wrapper
   return outer

@format_hrefs()
def get_html():
   content = """
     <!DOCTYPE html>
     <html>
      <body>
        <p>An absolute URL: https://www.w3schools.com</p>
      </body>
     </html>
    """
   return content

print(get_html())

Вывод:

<!DOCTYPE html>
 <html>
  <body>
   <p>An absolute URL: <a href="https://www.w3schools.com" _target="blank" class="">https://www.w3schools.com</a></p>
  </body>
</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...