Ответы пользователя по тегу Beautiful Soup
  • Как корректно использовать селектор при парсинге сайта?

    SoreMix
    @SoreMix
    yellow
    1. el.select('.messageContain.copy-text')
    2. А авторизация и некий антиспам продуманы уже я надеюсь? requests понятия не имеет что за диалог у вас идет в браузере. Не факт что вообще вернется страница в таком виде в каком должна быть, вдруг диалоги XHR подгружаются

    Плюс, важная вещь - научиться смотреть что пришло в ответ на запрос. То что в браузере - пусть будет в браузере, это не ваша страница, ваша - содержимое r.content. Берем это содержимое, льем в файл и изучаем
    Ответ написан
    Комментировать
  • Почему выдаёт ошибку AttributeError: 'NoneType' object has no attribute 'select'?

    SoreMix
    @SoreMix
    yellow
    Значит не нашелся такой элемент в супе
    Ответ написан
    Комментировать
  • Как извлечь текст из тега('a'), который находится в другом теге ('td') с классом?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    Чтобы найти теги а, которые лежат в тегах td нужно
    1. Найти теги td
    2. Найти в них теги а
    3. Взять текст

    for td in soup.find_all(“td”, attrs={“class”: “titleColumn”}):
        a = td.find(“a”)
        print(a.text)
    Ответ написан
    1 комментарий
  • Как это спарсить?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    soup.find('div', attrs={'set': 'Fade'}).text
    ну или
    soup.find('div', attrs={'class': 'info'}).find('div').text
    Ответ написан
  • Как парсить данные python, если много тегов?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    Данные динамически рисуются на сайте, поэтому None

    https://qna.habr.com/q/1038438#answer_2008702
    Ответ написан
  • Не работает requests, readmanga выдает 402, что делать?

    SoreMix
    @SoreMix
    yellow
    Нужно завести себе привычку, при отправке запросов, добавлять в заголовки хотя бы User-Agent от нормального браузера. Большинство проблем сразу отпадет

    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'}
    response = requests.get(url, headers=headers)
    Ответ написан
    Комментировать
  • Как мне парсить это?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    А что в строке for pg in text.find("div", "dle-content"): искали? Класс? Пропустили имя параметра
    Ответ написан
  • Как парсить используя библиотеку BeautifulSoup4 Python?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    from bs4 import BeautifulSoup
    
    html = '''
    <div class="soundTitle sc-clearfix sc-hyphenate sc-type-h2 sc-text-h4 streamContext m-interactive"><div class="soundTitle__titleContainer">
        <div class="soundTitle__playButton">
            <a role="button" href="" class="snippetUXPlayButton sc-button-play playButton sc-button sc-button-xlarge" tabindex="0" title="Play" draggable="true">Play</a>
        </div>
    
      <div class="soundTitle__usernameTitleContainer">
          <div class="sc-type-light sc-text-secondary sc-text-h4 soundTitle__secondary">
            <a href="/gracedaviesofficial" class="soundTitle__username sc-link-secondary
                 sc-link-light">
              <span class="soundTitle__usernameText">
                  Grace Davies
              </span>
            </a>
                  </div>
            <a class="sc-link-primary soundTitle__title sc-link-dark sc-text-h4" href="/gracedaviesofficial/hello-adele">
                <span class="">Hello - Adele</span>
            </a>
      </div>
      <div class="soundTitle__additionalContainer sc-ml-1.5x">
          <div class="soundTitle__uploadTime sc-mb-0.5x">
            <time class="relativeTime" title="Posted on 26 October 2015" datetime="2015-10-26T14:51:09.000Z"><span class="sc-visuallyhidden">Posted 6 years ago</span><span aria-hidden="true">6 years ago</span></time>
          </div>
          <div class="soundTitle__tagContainer">
              <span class="sc-snippet-badge sc-selection-disabled sc-snippet-badge-medium sc-snippet-badge-grey sc-hidden"></span>
              <span class="sc-snippet-badge sc-selection-disabled sc-snippet-badge-small sc-snippet-badge-grey sc-hidden"></span>
              <a class="sc-tag soundTitle__tag sc-tag-small" href="/tags/hello"><span class="sc-truncate sc-tagContent">hello</span></a>
          </div>
      </div>
    </div>
    </div>
    '''
    
    soup = BeautifulSoup(html, 'html.parser')
    
    a_tags = soup.find_all('a', {'class': 'soundTitle__title'})
    
    for a_tag in a_tags:
        print(a_tag['href'], a_tag.find('span').text)
    Ответ написан
    Комментировать
  • Почему beautifulSoup не парсит скрытое значение?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    Значит контент подгрузился динамически, дело не в BS4. Изучайте историю запросов

    https://qna.habr.com/q/1038438#answer_2008702
    Ответ написан
    Комментировать
  • Расширение таблицы при парсинге?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    В общем, рассказываю про парсинг.

    Код, который видно на странице через инспектор элементов в браузере - это код, который браузер подготовил для пользователя. Открываете сайт - браузер отправлять запрос на сервер. Запрос состоит из метода, пути, заголовков и тела. После первоначального запроса браузер получает от сервера HTML страницу, в которую включено (обычно) множество JS скриптов, которые в процессе выполнения могут создавать дополнительные запросы на сервер для получения дополнительной информации. После выполнения всех действий, пользователь видит в браузере готовый результат, который отличается от первоначального запроса из-за дополнительных джаваскриптов.

    Если элемент (класс, id, и тд) видно в инспекторе браузера - это не означает, что элемент присутствовал при первоначальном запросе. Чтобы увидеть тот код, который браузер получает первоначально (тот самый код, который вы получите через requests, curl итд) - нужно нажать CTRL+U, либо правой кнопкой -> просмотр кода страницы
    Это - тот самый код, который вы получаете, и все данные нужно искать только в нем, это дает гарантию того, что нужный вам элемент будет присутствовать при выполнении запросов через ЯП.

    Если нужного элемента нет на странице, значит он загружен каким нибудь JS скриптом. Здесь будут два варианта:
    1. JS отправляет дополнительный запрос на сервер, получает нужные данные и вставляет их в HTML.
    2. Данные создаются внутри JS скрипта без запросов (очень маловероятно)

    Если данные появляются в результате дополнительного запроса, то нужно просто повторить этот запрос.

    Чтобы понять, что нужно - нужно воспользоваться любым сниффером трафика. Самое простое - встроенный в браузер логгер запросов. F12 -> Network.
    6124fec4cfd69347854863.png
    Обычно достаточно поставить фильтр на XHR.
    Если есть под рукой Fiddler, то тоже сгодится. Ну и Burp / ZAP как вариант (но очень жирно).

    Алгоритм будет примерно таким:
    1. Открываем вкладку Network
    2. Очищаем историю запросов (если есть)
    3. Желательно поставить галочку "Preserve log", чтобы история не пропадала.
    4. Обновляем страницу. Если контент подгружается при прокретке / по нажатию кнопки - крутим / нажимаем и тд.
    5. Теперь можно нажать CTRL+F все в той же вкладке Network и вписать искомый текст (допустим название товара).
    6. Слева будут те запросы, которые содержат эту подстроку. Теперь нужно просто пощелкать по ним, найти нужный, посмотреть из чего он состоит и повторить его через requests.

    Нужно обратить внимание на заголовки и тело запроса. Не редко при загрузке доп. информации в тело запроса так же передается указатель текущей страницы, или индекс элемента, с которого начинается новый список. Так же в заголовки могут добавиться дополнительные. Например, csrf token, либо X-Requested-With. Если повторение запроса не принесло желанный результат - стоит проверить заголовки и тело еще раз. Если сайт загружает данные при нажатии на кнопки, прокрутке страницы и тд - алгоритм тот же.

    Делюсь хорошим сайтом, который увидел тут: https://curl.trillworks.com/
    Копируете свой запрос как CURL
    612500b91076a776091384.png
    Затем вставляете на сайт. Он выдаст готовый код на Python. Но нужно понимать, что это автоматический процесс и он не всегда выдает правильный результат. В частности, преобразование application/json тела довольно неправильно. Но для копипаста некоторых заголовков подходит вполне. В общем сайтом пользоваться можно, но и самому думать тоже нужно

    Из хороших программ - Postman. Позволит легко и быстро составлять запросы, есть экспорт в Python код. Советую, если запросы довольно тяжелые, чтобы составлять их "наживую".

    Краткая выжимка:
    1. Код через инспектор браузера != коду с запроса requests / curl.
    2. Скорее всего нужные вам данные подгружаются доп. запросами, ищутся через любой мониторинг трафика.
    3. Следите за телом и заголовками запроса. Заголовки, даже самые незначительные, могут влиять на конечный результат.
    4. Старайтесь всегда в заголовки добавлять User-Agent

    Если данные грузятся без доп запросов, лежат в неизвестном формате, или просто лень разбираться - используйте Selenium. Он является таким же браузером, но только с возможностью контролировать его работу
    Ответ написан
    3 комментария
  • Почему BeautifulSoup.find_all() возвращает не все элементы удовлетворяющие условию на странице?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    Значит их нет в теле страницы. CTRL+U нажимайте и смотрите какие данные есть на странице
    Ответ написан
  • Python requests, при выводе всего сайта выводит body и после него: Request unsuccessful. Как пофиксить?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    Инкапсула - популярный cdn, с защитой от ботов, ддоса и прочего. Собственно, защищает сайт от подобного.
    Разве что искать обходы / писать свои
    Ответ написан
    Комментировать
  • Получить переменную JSON из BeautifulSoup Python?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    Такое просто в коде страницы лежит, да? Лучше регуляркой достать.

    import re
    html = '''window.__version__map = {
    'magicEditLoaderVersion': '0.0.75',
    'icbuPcDetailAll': '0.0.9'
    }
    window.detailData = {"globalData":{"asddsa":true}, "renderType":"js_ssr"}}}'''
    data = re.search(r'window.detailData = (.+?)$', html).group(1)


    Регулярка может измениться, в зависимости от того, какой там код на странице, но думаю логика ясна
    Ответ написан
    Комментировать
  • Python: Как спарсить ссылку, которая находится в стиле?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    Много разных подобных обсуждений прочитал, но ответа не нашёл

    Аттрибуты всех тегов можно получить просто по ключу как со словарем.

    from bs4 import BeautifulSoup
    
    html = '''<html lang="en">
    <body>
        <div class="UIMagicalImage_image RestaurantPageMenuItem_pictureImage" role="img" aria-label="Пример" style="background-image: url(&quot;https://primer.ru/test.jpeg&quot;);"></div>
    </body>
    </html>
    '''
    
    soup = BeautifulSoup(html, 'html.parser')
    div = soup.find('div')
    print(div['style'])


    Дальше уже как душе угодно, хоть через find, хоть через regex.

    import re
    url = re.search(r'(https?://.+?)"', div['style']).group(1)
    Ответ написан
  • Как получить от item.find то, что записано в class_?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    item_classes = item.get('class', [])
    Ответ написан
    Комментировать
  • Парсинг динамического сайта на python?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    Обычные graphql запросы. viewId всегда одинаковый судя по всему
    endCursor возвращается при каждом запросе

    import requests
    
    data = [{"operationName":"EventExhibitorList","variables":{"viewId":"RXZlbnRWaWV3XzE1MjUyMA==","search":"","selectedFilters":[{"mustEventFiltersIn":[]}]},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"ee232939a5b943c0d87a4877655179bc2e5c73472ff99814119deddb34e0a3b6"}}}]
    
    response = requests.post('https://api.swapcard.com/graphql', json=data).json()
    # парсим нужные данные тут
    
    end_cursor = response[0]['data']['view']['exhibitors']['pageInfo'].get('endCursor')
    
    while end_cursor:
        data = [{"operationName":"EventExhibitorList","variables":{"viewId":"RXZlbnRWaWV3XzE1MjUyMA==","search":"","selectedFilters":[{"mustEventFiltersIn":[]}],"endCursor":end_cursor},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"ee232939a5b943c0d87a4877655179bc2e5c73472ff99814119deddb34e0a3b6"}}}]
        
        response = requests.post('https://api.swapcard.com/graphql', json=data).json()
    
        # тут парсим нужные данные
    
        end_cursor = response[0]['data']['view']['exhibitors']['pageInfo'].get('endCursor')
    Ответ написан
    1 комментарий