Как создать веб-страницу доступных размеров продукта из Nike

#python #web-scraping

#python #веб-скрап

Вопрос:

Я пытаюсь создать веб-страницу всех доступных размеров со страницы продукта Nike. Например, эта страница:

https://www.nike.com/t/air-force-1-07-mens-shoe-JkTGzADv/315122-111

Я попытался загрузить веб-сайт и записать его в текстовый файл, подобный этому:

 import requests
from bs4 import BeautifulSoup

url = "https://www.nike.com/t/air-force-1-07-mens-shoe-JkTGzADv/315122-111"
page = requests.get(url)
soup = BeautifulSoup(page.content, 'html.parser')
soupstirng = str(soup)

with open("website.txt","w") as f:
    f.write(soupstirng)
    f.close()
  

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

Ответ №1:

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

Давайте решим это:

 import requests
import json

#Headers are highly recommended
headers = headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0',
    'Accept': 'image/webp,*/*',
    'Accept-Language': 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
    'Connection': 'keep-alive',
    'Pragma': 'no-cache',
    'Cache-Control': 'no-cache',
}
url = "https://www.nike.com/t/air-force-1-07-mens-shoe-JkTGzADv/315122-111"
page = requests.get(url,headers = headers)
soup = BeautifulSoup(page.content, 'html.parser')

#The web page is populated with data contained in a script tag which we will look for
#It is json data
data = json.loads(soup.find('script',text=re.compile('INITIAL_REDUX_STATE')).text.replace('window.INITIAL_REDUX_STATE=','')[0:-1])

#The Sku we are searching for
product_id = "315122-111"

#In the json file, the following will give us the possible SKUs list
skus = data['Threads']['products'][product_id]['skus']
#And the following their availability
available_skus = data['Threads']['products'][product_id]['availableSkus']

#Let's use pandas to cross both tables
df_skus = pd.DataFrame(skus)
df_available_skus = pd.DataFrame(available_skus)

#Here is finally the table with the available skus and their sizes
df_skus.merge(df_available_skus[['skuId','available']], on ='skuId')
# which can be saved in any format you want (xl, txt, csv, json...)
  

Вывод

 |       id |   nikeSize | skuId                                |   localizedSize | localizedSizePrefix   | available   |
|---------:|-----------:|:-------------------------------------|----------------:|:----------------------|:------------|
| 10042654 |       12.5 | 118cf6d0-e1c0-50ac-a620-7f3a7f9c0b64 |            47   | EU                    | True        |
| 10042656 |       14   | 0fb2d87f-a7f8-5e36-8961-99c35b0360c1 |            48.5 | EU                    | True        |
| 10042657 |       15   | f80a30b2-8a7c-5834-82c4-9bea2c0c9995 |            49.5 | EU                    | True        |
| 10042658 |       16   | 3e323cdc-1c35-5663-895e-f3f809edff1e |            50.5 | EU                    | True        |
  

Комментарии:

1. Большое вам спасибо за помощь, но почему-то я получаю эту ошибку: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

2. как странно, только что проверил, это работает на моей стороне. Вы получаете что-нибудь, когда вы print(soup.find('script',text=re.compile('INITIAL_REDUX_STATE')) ?

3. важно, чтобы вы использовали headers параметр : page = requests.get(url,headers = headers)

4. Хорошо, итак, я заставил это работать. Я data = json.loads(soup.find('script',text=re.compile('INITIAL_REDUX_STATE')).text.replace('window.INITIAL_REDUX_STATE=','')[0:-1]) заменил это: soupfind = soup.find('script',text = re.compile('INITIAL_REDUX_STATE')) soupstring = str(soupfind) textreplace = soupstring.replace('<script>window.INITIAL_REDUX_STATE=','')[0:-10] data = json.loads(textreplace) и знаю, что он отлично работает. Спасибо за вашу помощь 🙂 @Sebastien D