Как спарсить текст с проходом по ссылкам
Есть задача спарсить текст (например стихи) с сайта. Структура сайта устроена так, что на странице сайта расположены не сами стихи, а ссылки на них. Мне нужно, чтобы парсер проходил по ссылкам и забирал с них текст стихотворения и записывал в отдельный (или в один общий) текстовый файл.
Пример страницы сайта для парсинга https://stihi.ru/poems/selected.html
Подскажите возможно ли так сделать? Я пытался делать это в Powershell, но у меня все время получалось только спарсить текст только с текущей страницы (но не текст с каждой ссылки).
PS Я новичок и знаю только самые основы...
Ответы (2 шт):
Python - вне конкуренции :)
Вам понадобятся библиотеки requests для запросов и bs4 для парсинга результатов:
pip install bs4
pip install requests
Импортируйте их и укажите адрес ресурса:
import requests
from bs4 import BeautifulSoup
URL = 'https://stihi.ru'
Функция get_poems_data() сбора данных:
def get_poems_data() -> dict:
r = requests.get(f'{URL}/poems/selected.html')
soup = BeautifulSoup(r.content, 'html.parser')
poems_block = soup.find('ul', type='square')
poems_links = poems_ul.find_all('li')
poems_data = []
for row in poems_links:
data = row.find_all('a')
poems_data.append({
'title': data[0].text,
'author': data[1].text,
'link': URL + data[0]['href'],
})
return poems_data
возвращает список словарей с названием, автором и ссылкой:
data = get_poems_data()
>>> data
[
{'title': 'Новый путь', 'author': 'Вадим Бакулин', 'link': 'https://stihi.ru/editor/2021/02/10/617'},
{'title': 'Фонарики', 'author': 'Светлана Севрикова', 'link': 'https://stihi.ru/editor/2021/02/10/150'},
{'title': 'Талая вода', 'author': 'Мила Исаева', 'link': 'https://stihi.ru/editor/2021/02/10/1028'},
...
{'title': 'Она пыталась', 'author': 'Иван Грозный', 'link': 'https://stihi.ru/editor/2021/02/08/3106'},
{'title': 'Как лёгок день и радостен покой', 'author': 'Фокеева Елена', 'link': 'https://stihi.ru/editor/2021/02/09/4598'},
{'title': 'Как чудища, блаженные слова', 'author': 'Хубулава Григорий Геннадьевич', 'link': 'https://stihi.ru/editor/2021/02/08/7177'}
]
Функция get_poem_text(poem_link) пасинга текста:
def get_poem_text(poem_link: str) -> str:
r = requests.get(t_url)
soup = BeautifulSoup(r.content, 'html.parser')
text = soup.find('div', class_='text').text
return text
возвращает текст, например, последнего стиха в data:
>>> print(get_poem_text(data[-1]['link']))
Как чудища, блаженные слова,
Бросаются ко мне голодной стаей,
Строфу железной рифмой подковав,
Я их ловлю и долго приручаю.
Ныряю в детский, сумасшедший гам,
Где смех уже неотличим от стона,
И громко называю, как Адам,
Жар-птицу, саламандру и дракона.
Рычат они, напав на чужака,
Как будто им кошмар докучный снится,
И сами выбирают ездока,
Когда ему готовы подчиниться.
Строптивы, непокорны до конца,
Никто из них добром служить не хочет...
Рождается из схватки пара строчек,
Как золото из серого свинца.
И записать в файл:
with open(f"{data[-1]['title']}.txt", "w") as file:
file.write(get_poem_text(data[-1]['link']))
в директории, откуда запускался файл, будет новый .txt: Как чудища, блаженные слова.txt...
Python - вне конкуренции :)
Был бы, если бы:
- мог решать большинство задач "из коробки", а не с помощью предварительного
pip install - не было прочих интерпретаторов
PowerShell в его нынешнем виде (то есть pwsh) способен решать "из коробки" (при наличии рук не из задницы) огромное количество задач. Ну разве что научного характера задачи лучше решаются в Julia.
Как поставленная задача может быть решена в pwsh?
$com = New-Object -ComObject HTMLFile
# берём только первое стихотворение, если нужно скопом - используем foreeach
$com.write([ref](Invoke-WebRequest "https://stihi.ru$((
Invoke-WebRequest https://stihi.ru/poems/selected.html
).Links.Where{$_.class -eq 'poemlink'}[0].href)").Content)
$com.getElementsByClassName('text')[0].innerText | Out-File C:\somefile.txt -Append
[void][Runtime.InteropServices.Marshal]::ReleaseComObject($com)