Nano Hash - криптовалюты, майнинг, программирование

BeautifulSoup: анализировать динамический контент JavaScript

Я разрабатываю скрейпер на Python с помощью BeautifulSoup, который анализирует списки продуктов из этот веб-сайт и извлекает некоторую информацию для каждого списка продуктов (например, цену, поставщика и т. д.). Я могу извлечь большую часть этой информации, кроме одной (то есть количества товара), которая кажется скрытой из необработанного html. Глядя на веб-страницу в моем браузере, я вижу (unid = unit):

product_name       1 unid      $10.00 

но html для этого не показывает никакого целочисленного значения, которое я могу извлечь. Он показывает этот html-текст:

<div class="e-col5 e-col5-offmktplace ">
  <div class="kWlJn zYaQqZ gQvJw">&nbsp;</div> 
  <div class="imgnum-unid"> unid</div>
</div>

Мой вопрос: как мне получить этот скрытый контент e-col5, в котором хранится количество товара?

import re
import requests
from bs4 import BeautifulSoup

page = requests.get("https://ligamagic.com.br/?view=cards%2Fsearch&card=Hapatra%2C+Vizier+of+Poisons")
soup = BeautifulSoup(page.content, 'html.parser')
vendor = soup.find_all('div', class_="estoque-linha", mp="2")
print(vendor[1].find(class_='e-col1').find('img')['title'])
print(vendor[1].find(class_='e-col2').find_all(class_='ed-simb')[1].string)
print(vendor[1].find(class_='e-col5'))

EDIT: Скрытый контент в данном случае означает динамически обновляемый контент JavasSript.


  • Похоже, что якобы скрытый контент на самом деле динамически обновляется с помощью JavaScript. 25.12.2018
  • Как правильно анализировать этот тип контента @LukaszSalitra? 25.12.2018
  • @delirium в общем случае это сложно. В вашем конкретном случае может потребоваться изучить JavaScript, чтобы увидеть, что он делает, и в основном повторно реализовать его в своем синтаксическом анализаторе. 25.12.2018

Ответы:


1

unid сохраняется в массиве JS

vetFiltro[0]=["e3724364",0,1,....];

1 - это unid, вы можете получить его с помощью регулярного выражения

# e-col5
unitID = vendor[1].get('id').replace('line_', '') # line_e3724364 => e3724364
regEx = r'"%s",\d,(\d+)' % unitID
unit = re.search(regEx, page.text).group(1)
print(unit + ' unids')
25.12.2018
  • Спасибо за помощь! Как ты это узнал? Могу ли я обрабатывать любые другие подобные поля JavaScript (например, цену)? 25.12.2018
  • К сожалению, я не могу найти способ получить цену. 25.12.2018
  • Спасибо, в любом случае. Не могли бы вы еще прокомментировать, как вы узнали о vetFiltro? 25.12.2018
  • у каждого поставщика есть идентификатор типа line_e3724364 с удаленным line_, который я нашел в источнике страницы. и пожалуйста. 25.12.2018

  • 2

    Если вы присмотритесь, unid — это просто изображение в div, перемещенное с помощью class к правильному номеру.

    Например unid 1:

    .jLsXy {
        background-image: url(arquivos/up/comp/imgunid/files/img/181224lSfWip8i1lmcj2a520836c8932ewcn.jpg);
    }
    

    это изображение, содержащее числа.

    .gBpKxZ {
    background-position: -424px -23px;
    }
    

    это класс для числа 1

    Так что найдите соответствующий номер css и создайте свою таблицу (простой способ), но не лучший способ.

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

    Edit2 Я использовал chrome devtools. Если вы осмотрите unid, вы также найдете css для каждого класса. Итак, после проверки URL стало ясно.

    25.12.2018
  • Спасибо за вашу помощь :) ! Как вы узнали, что число является изображением? 25.12.2018
  • @delirium проверьте второе редактирование :), если вам нужно больше объяснений, просто спросите меня :) 25.12.2018

  • 3

    @ewwink нашел способ вытащить unid, но не смог вытащить цены. Я попытался вытащить цены в этом ответе.

    Целевой фрагмент div:

    <div mp="2" id="line_e3724364" class="estoque-linha primeiro"><div class="e-col1"><a href="b/?p=e3724364" target="_blank"><img title="Rayearth Games" src="//www.lmcorp.com.br/arquivos/up/ecom/comparador/155937.jpg"></a></div><div class="e-col9-mobile"><div class="e-mob-edicao"><img src="//www.lmcorp.com.br/arquivos/up/ed_mtg/AKH_R.gif" height="19"></div><div class="e-mob-edicao-lbl"><p>Amonkhet</p></div><div class="e-mob-preco e-mob-preco-desconto"><font color="gray" class="mob-preco-desconto"><s>R$ 1,00</s></font><br>R$ 0,85</div></div><div class="e-col2"><a href="./?view=cards/search&amp;card=ed=akh" class="ed-simb"><img src="//www.lmcorp.com.br/arquivos/up/ed_mtg/AKH_R.gif" height="21"></a><font class="nomeedicao"><a href="./?view=cards/search&amp;card=ed=akh" class="ed-simb">Amonkhet</a></font></div><div class="e-col3"><font color="gray" class="mob-preco-desconto"><s>R$ 1,00</s></font><br>R$ 0,85</div>
                                <div class="e-col4 e-col4-offmktplace">
                                    <img src="https://www.lmcorp.com.br/arquivos/img/bandeiras/pten.gif" title="Português/Inglês"> <font class="azul" onclick="cardQualidade(3);">SP</font>
    
                                </div>
                            <div class="e-col5 e-col5-offmktplace "><div class="cIiVr lHfXpZ mZkHz">&nbsp;</div> <div class="imgnum-unid"> unid</div></div><div class="e-col8 e-col8-offmktplace "><div><a target="_blank" href="b/?p=e3724364" class="goto" title="Visitar Loja">Ir à loja</a></div></div></div>
    

    Если мы внимательно посмотрим, мы можем,

    for item in soup.findAll('div', {"id": re.compile('^line')}):
     print(re.findall("R\$ (.*?)</div>", str(item), re.DOTALL))
    

    Вывод [усеченный]:

    ['10,00</s></font><br/>R$ 8,00', '10,00</s></font><br/>R$ 8,00']
    ['9,50</s></font><br/>R$ 8,55', '9,50</s></font><br/>R$ 8,55']
    ['9,50</s></font><br/>R$ 8,55', '9,50</s></font><br/>R$ 8,55']
    ['9,75</s></font><br/>R$ 8,78', '9,75</s></font><br/>R$ 8,78']
    []
    []
    

    Он извлекает основные куски, и мы узнаем цены. Но это также пропускает несколько элементов.

    Чтобы получить все данные, мы можем использовать OCR API и Selenium. Мы можем зафиксировать интересующие элементы, используя следующий фрагмент:

    from selenium import webdriver
    from PIL import Image
    from io import BytesIO
    
    fox = webdriver.Firefox()
    fox.get('https://ligamagic.com.br/?view=cards%2Fsearch&card=Hapatra%2C+Vizier+of+Poisons')
    #element = fox.find_element_by_id('line_e3724364')
    element = fox.find_elements_by_tag_name('s')
    location = element.location
    size = element.size
    png = fox.get_screenshot_as_png() # saves screenshot of entire page
    fox.quit()
    
    im = Image.open(BytesIO(png)) # uses PIL library to open image in memory
    
    left = location['x']
    top = location['y']
    right = location['x'] + size['width']
    bottom = location['y'] + size['height']
    
    
    im = im.crop((left, top, right, bottom)) # defines crop points
    im.save('screenshot.png') # saves new cropped image
    

    Воспользовался помощью https://stackoverflow.com/a/15870708.

    Мы можем повторить итерацию, как мы делали выше, используя re.findall() для сохранения всех изображений. После того, как у нас есть все изображения, мы можем использовать OCR Space для извлечения текстовых данных. Вот краткий фрагмент:

    import requests
    
    
    def ocr_space_file(filename, overlay=False, api_key='api_key', language='eng'):
    
        payload = {'isOverlayRequired': overlay,
                   'apikey': api_key,
                   'language': language,
                   }
        with open(filename, 'rb') as f:
            r = requests.post('https://api.ocr.space/parse/image',
                              files={filename: f},
                              data=payload,
                              )
        return r.content.decode()
    
    e = ocr_space_file(filename='1.png')
    
    print(e) # prints JSON
    

    1.png :

    введите здесь описание изображения

    Ответ в формате JSON от ocr.space :

    {"ParsedResults":[{"TextOverlay":{"Lines":[],"HasOverlay":false,"Message":"Text overlay is not provided as it is not requested"},"TextOrientation":"0","FileParseExitCode":1,"ParsedText":"RS 0',85 \r\n","ErrorMessage":"","ErrorDetails":""}],"OCRExitCode":1,"IsErroredOnProcessing":false,"ProcessingTimeInMilliseconds":"1996","SearchablePDFURL":"Searchable PDF not generated as it was not requested."}
    

    Это дает нам "ParsedText" : "RS 0',85 \r\n".

    25.12.2018
  • Хорошая работа! Как связать изображения с каждым списком? 26.12.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..