#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