Поиск на сайте при парсинге

https://jut.su/anime/ нужно запарсить каждую страницу после ввода названия аниме, не имею соображения как это сделать, как передать в строку ввода название ?


Ответы (2 шт):

Автор решения: Freekby

попробуйте, вместо того чтобы искать аниме в поисковой строке, спарсить ссылки и названия на аниме со всех страниц и сохранить их куда-нибудь, а уже после доставать ссылки и парсить нужные данные.

import requests
from bs4 import BeautifulSoup

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'}
page = 0
anime_list = dict()

while True:
    page += 1
    url = f'https://jut.su/anime/page-{page}'

    req = requests.post(url, headers=headers)
    soup = BeautifulSoup(req.text, 'lxml')
    all_anime_info = soup.find_all(class_='all_anime_global')

    if not all_anime_info:
        break

    print(page, '/ 28')

    for anime_info in all_anime_info:
        anime_name = anime_info.find(class_='aaname').text
        anime_link = 'https://jut.su' + anime_info.find('a').get('href')
        anime_list[anime_name] = anime_link

print(anime_list)

Но если вам хочется именно через поисковою строку, то лучше использовать Селениум.

→ Ссылка
Автор решения: gil9red

На странице сайта есть 2 элемента поиска:

  • Большой, с кнопкой Найти, оно вызывает POST запрос на /search/, который возвращает ответ с редиректом на конкретную страницу аниме
  • Ниже, Быстрый поиск ..., который POST запрос на /anime/ и возвращает список аниме, работает как фильтр

Я сделал пример для второго.

Описание:

  • Используем requests для отправки запроса на сайт:
    • Создаем сессию через requests.session(), чтобы иметь общие заголовки запросов и помнить куки, что сайт может возвращать для последующей отправки
    • Добавляем заголовок User-Agent, чтобы притвориться браузером
    • Отправляем POST запрос с данными формы через метод post. Данные заполняются через словарь в data. Данные для отправки посмотрел через браузер, используя инструмент инспектор, на вкладке Сети. Добавляем заголовок X-Requested-With, чтобы притвориться AJAX
  • Используем bs4 для парсинга
    • Для поиска использую css-селекторы, для них нужно использовать методы select и select_one
    • Ссылки на аниме относительные, а чтобы сделать их абсолютными использую функцию urljoin
  • Для стандартизации сбора данных создаем класс и dataclasses для автоматического создания конструктора, описания класса и т.п.

Думаю, на сайте результаты поиска могут разделены на страницы и подгружаться по мере пролистывания, эту логику не реализовывал

Зависимости:

  • pip install requests
  • pip install bs4

Пример:

from dataclasses import dataclass
from urllib.parse import urljoin
from typing import List

from bs4 import BeautifulSoup
import requests


@dataclass
class Anime:
    url: str
    title: str


session = requests.session()
session.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0'


def search(text: str) -> List[Anime]:
    data = {
        'ajax_load': 'yes',
        'start_from_page': 1,
        'show_search': text,
        'anime_of_user': '',
    }
    headers = {
        'X-Requested-With': 'XMLHttpRequest',  # AJAX
    }
    rs = session.post('https://jut.su/anime/', headers=headers, data=data)
    rs.raise_for_status()

    items = []
    root = BeautifulSoup(rs.text, 'html.parser')
    for anime_el in root.select('.all_anime_global'):
        url = urljoin(rs.url, anime_el.a['href'])
        title = anime_el.select_one('.aaname').text

        items.append(Anime(url, title))

    return items

Проверяем:

for anime in search(text='гора'):
    print(anime)

Результат:

Anime(url='https://jut.su/shiki/', title='Усопшие')
Anime(url='https://jut.su/slime-taoshite-300-nen/', title='Убивала слизней 300 лет до максимального уровня')
Anime(url='https://jut.su/reikenzan/', title='Гора Священного меча')
Anime(url='https://jut.su/shakunetsu-kabaddi/', title='Пылающий Кабадди')
→ Ссылка