Красивый суп не возвращает все теги - PullRequest
0 голосов
/ 11 июля 2019

Я новичок в изучении веб-страниц и использую python3 вместе с beautifulsoup4 для сбора информации о некоторых телефонах с этого сайта att.com .

Вот мой код для извлечения внешнего div каждого телефона из HTML (здесь всего 49 телефонов).

from bs4 import BeautifulSoup
import requests
import csv

source = requests.get('https://www.att.com/buy/phones/').text
#soup = BeautifulSoup(source,'lxml')
#soup = BeautifulSoup(source,'html5lib')
soup  = BeautifulSoup(source,'html.parser')
phone_div=soup.findAll('div',class_='_1hOzu')
#phone_div=soup.findAll('div',class_='_2Ldwa')
#phone_div=soup.find('div',class_='_3kwdR')
#phone_div=soup.findAll('div',class_='_1BGB4')
print(phone_div[1].prettify())
print(phone_div[5].prettify())

Вот вывод для первого телефонного раздела (аналогично первым четырем телефонам), содержащий всю информацию об имени телефона, цене и т. Д .:

<div class="_1hOzu">
 <div class="_14rcf _1NPjc false false" data-index="1" tabindex="0">
  <a class="_3-Yg9 _13w_Y" data-qa="DeviceTile-PDPlink-iPhone XS Max" href="/buy/phones/apple-iphone-xs-max-64gb-silver.html" tabindex="-1">
   <div class="_27UM0 false">
    <div class="_3C82I">
     <div class="_bOwfD">
      <span class="_2VSUp">
       Buy one, give one.
      </span>
     </div>
    </div>
   </div>
   <div class="_2pI5U">
    <div class="_3AUSX">
     <i class="_3cKi3" style="height:50px;width:50px">
     </i>
    </div>
    <div class="_VzvqU">
    </div>
   </div>
   <div>
    <div class="_1bjup">
     <div>
      <div class="_2Ldwa">
       APPLE
      </div>
      <div>
       <div class="_1BGB4">
        iPhone XS Max
       </div>
       <div class="_izQNb">
        placeholder
       </div>
      </div>
     </div>
    </div>
    <div class="_1NK_S">
     <div class="_1O0IX">
      <div class="_3AUSX">
       <i class="_3cKi3" style="height:50px;width:50px">
       </i>
      </div>
     </div>
    </div>
    <div>
     <div class="_3JaQ9 ">
      <div class="_1dPLs _3yvoJ _38PTM">
       <label class="_1ih28">
        <i class="_9V5dD _10JvD">
        </i>
        <span class="_1C-NR">
         Star Ratings
        </span>
        <input class="_ZI8n9" name="Customer Reviews" readonly="" type="radio" value="1"/>
       </label>
       <label class="_1ih28">
        <i class="_9V5dD _10JvD">
        </i>
        <span class="_1C-NR">
         Star Ratings
        </span>
        <input class="_ZI8n9" name="Customer Reviews" readonly="" type="radio" value="2"/>
       </label>
       <label class="_1ih28">
        <i class="_9V5dD _10JvD">
        </i>
        <span class="_1C-NR">
         Star Ratings
        </span>
        <input class="_ZI8n9" name="Customer Reviews" readonly="" type="radio" value="3"/>
       </label>
       <label class="_1ih28">
        <i class="_9V5dD _10JvD">
        </i>
        <span class="_1C-NR">
         Star Ratings
        </span>
        <input class="_ZI8n9" name="Customer Reviews" readonly="" type="radio" value="4"/>
       </label>
       <label class="_1ih28">
        <i class="_18XCu _10JvD">
        </i>
        <i class="_fLbUs _9V5dD _10JvD" style="width:58.95%">
        </i>
        <span class="_1C-NR">
         Star Ratings
        </span>
        <input class="_ZI8n9" name="Customer Reviews" readonly="" type="radio" value="5"/>
       </label>
      </div>
      <span>
       4.6
       <span class="_VCKql">
        |
       </span>
       531
      </span>
     </div>
     <p class="_2bs9E ">
      $36.67
      <span class="_31cDG">
       /mo.
      </span>
     </p>
    </div>
    <div class="_1YUjH">
     <div>
     </div>
     <div class="_3gbuG">
      <div>
       Req.’s 0% APR 30-mo. installment agmt, qual. credit and service.
      </div>
      <div class="_3gbuG">
       <button class="_1oGNe" data-index="1" data-qa="DeviceTilePLP-SeePriceDetails" tabindex="0">
        See
        <!-- -->
        price details.
       </button>
      </div>
     </div>
    </div>
    <div class="_3_rcU">
    </div>
   </div>
   <div class="_37Icd ">
   </div>
  </a>
 </div>
</div>

Вывод оставшихся телефонных номеров:

<div class="_1hOzu">
 <div class="_14rcf _1NPjc false false" data-index="5" tabindex="0">
  <div class="_3AUSX">
   <i class="_3cKi3" style="height:50px;width:50px">
   </i>
  </div>
 </div>
</div>

Не удается получить все вложенные внутренние теги для оставшихся элементов div, и, следовательно, я не могу извлечь из него что-либо. Я уже прочитал некоторые ответы SO об отсутствующих внутренних тегах и попытался использовать разные парсеры на основе этих ответов, но это не помогло. Есть идеи, где я могу ошибаться ??

Ответы [ 2 ]

0 голосов
/ 11 июля 2019

Данные загружаются через Javascript, но содержимое находится внутри страницы. С помощью некоторого регулярного выражения мы можем извлечь содержимое Json (полное содержимое хранится в переменной data):

import re
import json
import requests

url = 'https://www.att.com/buy/phones/'
html_text = requests.get(url).text

data = json.loads(re.findall(r'__NEXT_DATA__ = (.*?});', html_text)[0])
print(json.dumps(data['props']['pageProps']['deviceList'], indent=4))

Печать:

[
    {
        "color": "Black",
        "manufacturerShortName": "apple",
        "paymentType": "postpaid",
        "deviceSubType": "pda",
        "iotDevice": false,
        "starRatings": 4.6092,
        "newArrival": false,
        "imageUrl": "https://www.att.com/catalog/en/skus/images/apple-iphone%20xr-black-100x160.jpg",
        "model": "iPhone XR",
        "brand": "Apple",
        "skuId": "sku9240254",
        "displayContentItems": [
            {
                "displayType": "ribbon",
                "contentSource": "cms",
                "marketingPriority": 1,
                "flowTypes": [
                    "NEW",
                    "UP",
                    "AL"
                ],
                "enable": true,
                "description": "Buy one, give one.",
                "customerTypes": [
                    "CRU"
                ],
                "contentType": "image"
            },
            {
                "displayType": "ribbon",
                "contentSource": "cms",
                "marketingPriority": 1,
                "flowTypes": [
                    "NEW",
                    "UP",
                    "AL"
                ],
                "enable": true,
                "description": "Buy one, give one.",
                "customerTypes": [
                    "CONSUMER",
                    "IRU"
                ],
                "contentType": "image"
            },

...and so on.
0 голосов
/ 11 июля 2019

Это потому, что запросы являются динамическими запросами, метод запроса не возвращает все теги, которые вы видите в элементе inspect.(Проверьте исходный код страницы, вот что вы получите в ответ)

Для получения этих данных вместо простого request попробуйте запрос selenium.Он будет возвращать динамический ответ, такой как элемент inspect.

Пример:

from bs4 import BeautifulSoup
from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.att.com/buy/phones/')
content = BeautifulSoup(driver.page_source, 'html.parser')
phone_div=content.findAll('div',class_='_1hOzu')
print(phone_div[1].prettify())
print(phone_div[5].prettify())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...