Проблема с заменой тегов на новую строку с помощью bs4

Проблема: я не могу заменить <br> теги с символом новой строки, используя Beautiful Soup 4.

Код: Моя программа (соответствующая часть) в настоящее время выглядит

for br in board.select('br'):
    br.replace_with('\n')

но я также пытался board.find_all() на месте board.select(),

Результаты: Когда я использую board.replace_with('\n') все <br> теги заменяются строковым литералом \n, Например, <p>Hello<br>world</p> в конечном итоге станет Hello\nworld, С помощью board.replace_with(\n) вызывает ошибку

File "<ipython-input-27-cdfade950fdf>", line 10
    br.replace_with(\n)
                       ^
SyntaxError: unexpected character after line continuation character

Другая информация: я использую Блокнот Jupyter, если это имеет какое-либо отношение. Вот моя полная программа, так как в другом месте я мог не заметить некоторые проблемы.

import requests
from bs4 import BeautifulSoup
import pandas as pd

page = requests.get("https://boards.4chan.org/g/")
soup = BeautifulSoup(page.content, 'html.parser')
board = soup.find('div', class_='board')

for br in board.select('br'):
    br.replace_with('\n')

message = [obj.get_text() for obj in board.select('.opContainer .postMessage')]
image = [obj['href'] for obj in board.select('.opContainer .fileThumb')]
pid = [obj.get_text() for obj in board.select('.opContainer .postInfo .postNum a[title="Reply to this post"]')]
time = [obj.get_text() for obj in board.select('.opContainer .postInfo .dateTime')]

for x in range(len(image)):
    image[x] = "https:" + image[x]

post = pd.DataFrame({
    "ID": pid,
    "Time": time,
    "Image": image,
    "Message": message,
    })
post

pd.options.display.max_rows
pd.set_option('display.max_colwidth', -1)

display(post)

Любой совет будет принят во внимание. Спасибо за чтение.

4 ответа

Просто попробовал, и у меня это работает, моя версия bs4 - 4.8.0, и я использую Python 3.5.3, например:

from bs4 import BeautifulSoup

soup = BeautifulSoup('hello<br>world')

for br in soup('br'):
    br.replace_with('\n')

# <br> was replaced with \n successfully
assert str(soup) == '<html><body><p>hello\nworld</p></body></html>'

# get_text() also works as expected
assert soup.get_text() == 'hello\nworld' 

# it is a \n not a \\n 
assert soup.get_text() != 'hello\\nworld'

Я не привык работать с Jupyter Notebook, но, похоже, ваша проблема в том, что все, что вы используете для визуализации данных, показывает вам строковое представление вместо фактической печати строки, надеюсь, это поможет, С уважением, adb

Вместо замены после преобразования в суп, попробуйте заменить <br> теги перед преобразованием. Подобно,

soup = BeautifulSoup(str(page.content).replace('<br>', '\n'), 'html.parser')

Надеюсь это поможет! Ура!

PS: я не получил никакой логической причины, почему это не работает после превращения в суп.

После экспериментов с вариациями

page = requests.get("https://boards.4chan.org/g/")
str_page = page.content.decode()
str_split = '\n<'.join(str_page.split('<'))
str_split = '>\n'.join(str_split.split('>'))
str_split = str_split.replace('\n', '')
str_split = str_split.replace('<br>', ' ')
soup = BeautifulSoup(str_split.encode(), 'html.parser')

в течение большей части двух часов я определил, что фрейм данных Panda печатает символ новой строки как строковый литерал. Все остальное указывает на то, что программа работает так, как задумано, поэтому я предполагаю, что это было проблемой с самого начала.

по какой-то причине прямая замена с новой строкой не работает с bs4, вы должны сначала заменить какой-либо другой уникальный символ (предпочтительно последовательность символов), а затем заменить эту последовательность в тексте на новую строку.

попробуй это.

      for br in soup.find_all('br'): br.replace_with('+++')
text=soup.get_text().replace('+++','\n)
Другие вопросы по тегам