【问题标题】:How to webscrape all shoes on nike page using python如何使用python在nike页面上抓取所有鞋子
【发布时间】:2020-07-20 16:02:25
【问题描述】:

我正在尝试抓取https://www.nike.com/w/mens-shoes-nik1zy7ok 上的所有鞋子。如何抓取所有鞋子,包括向下滚动页面时加载的鞋子?

我想要获取的确切信息在类“product-card__body”的 div 元素中 如下:

<div class="product-card__body " data-el-type="Card"><figure><a class="product-card__link-overlay" href="https://www.nike.com/t/air-force-1-07-mens-shoe-TjqcX1/CJ0952-001">Nike Air Force 1 '07</a><a class="product-card__img-link-overlay" href="https://www.nike.com/t/air-force-1-07-mens-shoe-TjqcX1/CJ0952-001" aria-describedby="Nike Air Force 1 '07" data-el-type="Hero"><div class="image-loader css-zrrhrw product-card__hero-image is--loaded"><picture><source srcset="https://static.nike.com/a/images/c_limit,w_592,f_auto/t_product_v1/s12ff321cn2nykxhva9j/air-force-1-07-mens-shoe-TjqcX1.jpg" media="(min-width: 1024px)"><source srcset="https://static.nike.com/a/images/c_limit,w_592,f_auto/t_product_v1/s12ff321cn2nykxhva9j/air-force-1-07-mens-shoe-TjqcX1.jpg" media="(max-width: 1023px) and (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)"><source srcset="https://static.nike.com/a/images/c_limit,w_318,f_auto/t_product_v1/s12ff321cn2nykxhva9j/air-force-1-07-mens-shoe-TjqcX1.jpg" media="(max-width: 1023px)"><img src="https://static.nike.com/a/images/c_limit,w_318,f_auto/t_product_v1/s12ff321cn2nykxhva9j/air-force-1-07-mens-shoe-TjqcX1.jpg" alt="Nike Air Force 1 '07 Men's Shoe"></picture></div></a><div class="product-card__info"><div class="product_msg_info"><div class="product-card__titles"><div class="product-card__title " id="Nike Air Force 1 '07">Nike Air Force 1 '07</div><div class="product-card__subtitle ">Men's Shoe</div></div></div><div class="product-card__count-wrapper show--all"><div class="product-card__count-item"><button type="button" aria-expanded="false" class="product-card__colorway-btn"><div aria-label="Available in 3 Colors" aria-describedby="Nike Air Force 1 '07" class="product-card__product-count "><span>3 Colors</span></div></button></div></div><div class="product-card__price-wrapper "><div class="product-card__price"><div><div class="product-price css-11s12ax is--current-price" data-test="product-price">$90</div></div></div></div></div></figure></div>

这是我正在使用的代码:

    html_data = requests.get("https://www.nike.com/w/mens-shoes-nik1zy7ok").text
    shoes = json.loads(re.search(r'window.INITIAL_REDUX_STATE=(\{.*?\});', html_data).group(1))

现在它只检索最初加载到页面上的鞋子。我如何获得其余的鞋子并将其附加到 shoes 变量中?

【问题讨论】:

  • 从您使用的标签来看,您已经知道BeautifulSouprequests,因此您已准备好实现此功能。你写了什么代码,你到底在哪里遇到问题?
  • @ForceBru 检查编辑
  • requests.get() 将获取一个 html 页面。鞋子通过 JavaScript 加载到页面上。您可能可以直接调用 API(使用开发工具检查请求和 Postman 以查看是否可以调用它)。或者使用 selenium 之类的包。
  • 嗨 Greg,我如何确定要调用的 API URL?

标签: python python-3.x web-scraping beautifulsoup python-requests


【解决方案1】:

通过检查网站发出的 API 调用,您可以找到一个以 https://api.nike.com/ 开头的神秘 URL。此 URL 还存储在您已用于获取前几个产品的 INITIAL_REDUX_STATE 中。所以,我只是扩展你的方法:

import requests
import json
import re

# your product page
uri = 'https://www.nike.com/w/mens-shoes-nik1zy7ok'

base_url = 'https://api.nike.com'
session = requests.Session()

def get_lazy_products(stub, products):
"""Get the lazily loaded products."""
    response = session.get(base_url + stub).json()
    next_products = response['pages']['next']
    products += response['objects']
    if next_products:
        get_lazy_products(next_products, products)
    return products

# find INITIAL_REDUX_STATE
html_data = session.get(uri).text
redux = json.loads(re.search(r'window.INITIAL_REDUX_STATE=(\{.*?\});', html_data).group(1))

# find the initial products and the api entry point for the recursive loading of additional products
wall = redux['Wall']
initial_products = re.sub('anchor=[0-9]+', 'anchor=0', wall['pageData']['next'])

# find all the products
products = get_lazy_products(initial_products, [])

# Optional: filter by id to get a list with unique products
cloudProductIds = set()
unique_products = []
for product in products:
    try:
        if not product['id'] in cloudProductIds:
            cloudProductIds.add(product['id'])
            unique_products.append(product)
    except KeyError:
        print(product)

api 还返回产品的总数,尽管这个数字似乎有所不同,并且取决于 api 的 URL 中的 count 参数。

您需要帮助解析或汇总结果吗?

【讨论】:

  • 这很好,但是我如何指定我想要男鞋还是女鞋?
  • 我刚刚编辑了我之前的方法,因此您可以使用 URL 作为入口点(如 nike.com/w/mens-shoes-nik1zy7ok),然后查找所有产品。
  • 谢谢,但我一直收到此错误:redux = [script for script in scripts if script.text.startswith('window.INITIAL_REDUX_STATE')][0] IndexError: list index out of range
  • 它适用于我,但该行只是查找 INITIAL_REDUX_STATE 变量。我用你正在使用的正则表达式替换了它,这似乎对你有用。
  • 抱歉,我又做了一个更改,因为我意识到INITIAL_REDUX_STATE 中的产品与 api 返回的产品格式不同。现在所有产品的格式都相同。
猜你喜欢
  • 2019-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-07
相关资源
最近更新 更多