如何请求所有尺寸的库存 - Python

How to requests all sizes in stock - Python

我正在尝试向 Zalando 索取所有库存尺寸。自从我正在观看的视频以来,我不太清楚该怎么做 显示如何请求大小看起来与最小值不同。 我看的视频是这样的。 Video - 5.30

有谁知道如何索取库存尺寸并打印库存尺寸?

站点正在尝试请求大小:here

我的代码如下所示:

import requests
from bs4 import BeautifulSoup as bs

session = requests.session()

def get_sizes_in_stock():
    global session
    endpoint = "https://www.zalando.dk/nike-sportswear-air-max-90-sneakers-ni112o0bt-a11.html"
    response = session.get(endpoint)

    soup = bs(response.text, "html.parser")

我尝试转到查看页面源代码并查找尺寸,但我在页面源代码中看不到尺寸。

我希望有人能帮助我做什么。

尺寸在页面中

我在 html 的 javascript 标签中找到了它们,格式为

{
    "sku": "NI112O0BT-A110090000",
    "size": "42.5",
    "deliveryOptions": [
        {
            "deliveryTenderType": "FASTER"
        }
    ],
    "offer": {
        "price": {
            "promotional": null,
            "original": {
                "amount": 114500
            },
            "previous": null,
            "displayMode": null
        },
        "merchant": {
            "id": "810d1d00-4312-43e5-bd31-d8373fdd24c7"
        },
        "selectionContext": null,
        "isMeaningfulOffer": true,
        "displayFlags": [],
        "stock": {
            "quantity": "MANY"
        },
        "sku": "NI112O0BT-A110090000",
        "size": "42.5",
        "deliveryOptions": [
            {
                "deliveryTenderType": "FASTER"
            }
        ],
        "offer": {
            "price": {
                "promotional": null,
                "original": {
                    "amount": 114500
                },
                "previous": null,
                "displayMode": null
            },
            "merchant": {
                "id": "810d1d00-4312-43e5-bd31-d8373fdd24c7"
            },
            "selectionContext": null,
            "isMeaningfulOffer": true,
            "displayFlags": [],
            "stock": {
                "quantity": "MANY"
            }
        },
        "allOffers": [
            {
                "price": {
                    "promotional": null,
                    "original": {
                        "amount": 114500
                    },
                    "previous": null,
                    "displayMode": null
                },
                "merchant": {
                    "id": "810d1d00-4312-43e5-bd31-d8373fdd24c7"
                },
                "selectionContext": null,
                "isMeaningfulOffer": true,
                "displayFlags": [],
                "stock": {
                    "quantity": "MANY"
                },
                "deliveryOptions": [
                    {
                        "deliveryWindow": "2022-05-23 - 2022-05-25"
                    }
                ],
                "fulfillment": {
                    "kind": "ZALANDO"
                }
            }
        ]
    }
}

如果您使用 bs4 解析 html,您应该能够找到脚本标签并提取 JSON。

鞋子默认颜色的尺码显示在 html 中。旁边是其他颜色的 url。您可以将它们提取到字典和循环中,发出请求并提取不同的颜色及其可用性,我认为这是您实际请求的内容,如下所示(注意:我保持非常通用以避免硬编码键在请求之间发生变化) :

import requests, re, json

def get_color_results(link):
    headers = {"User-Agent": "Mozilla/5.0"}
    r = requests.get(link, headers=headers).text
    data = json.loads(re.search(r'(\{"enrichedEntity".*size.*)<\/script', r).group(1))
    results = []
    color = ""
    for i in data["graphqlCache"]:
        if "ern:product" in i:
            if "product" in data["graphqlCache"][i]["data"]:
                if "name" in data["graphqlCache"][i]["data"]["product"]:
                    results.append(data["graphqlCache"][i]["data"]["product"])
                if (
                    color == ""
                    and "color" in data["graphqlCache"][i]["data"]["product"]
                ):
                    color = data["graphqlCache"][i]["data"]["product"]["color"]["name"]
    return (color, results)


link = "https://www.zalando.dk/nike-sportswear-air-max-90-sneakers-ni112o0bt-a11.html"
final = {}
color, results = get_color_results(link)
colors = {
    j["node"]["color"]["name"]: j["node"]["uri"]
    for j in [
        a
        for b in [
            i["family"]["products"]["edges"]
            for i in results
            if "family" in i
            if "products" in i["family"]
        ]
        for a in b
    ]
}
final[color] = {
    j["size"]: j["offer"]["stock"]["quantity"]
    for j in [i for i in results if "simples" in i][0]["simples"]
}

for k, v in colors.items():
    if k not in final:
        color, results = get_color_results(v)
        final[color] = {
            j["size"]: j["offer"]["stock"]["quantity"]
            for j in [i for i in results if "simples" in i][0]["simples"]
        }

print(final)

聊天说明:

  1. 使用chrome浏览器导航至link

  2. Ctrl + U查看页面源码

  3. Ctrl + F在html

    中搜索38.5

    第一个匹配项是您已经知道的长字符串。该字符串很长,难以在页面源中导航并识别它是哪个标记的一部分。我可以通过多种方法从中识别出正确的脚本,但目前,一种简单的方法是:

from bs4 import BeautifulSoup as bs

link = 'https://www.zalando.dk/nike-sportswear-air-max-90-sneakers-ni112o0bt-a11.html'
headers = {'User-Agent':'Mozilla/5.0'}
r = requests.get(link, headers = headers)
soup = bs(r.text, 'lxml')

for i in soup.select('script[type="application/json"]'):
    if '38.5' in i.text:
        print(i)
        break

较慢的方法是:

soup.find("script", text=re.compile(r'.*38.5.*'))
  1. 虽然我使用 bs4 来获取正确的脚本标签内容,但这样我就知道了字符串的开头和结尾,表示我想使用的 JavaScript 对象 re 进行提取,然后使用 json 反序列化为 JSON 对象;这在 re-write 中使用 re 而不是 bs4 即在请求中的整个响应文本上使用 re 并传递将提取相同字符串的正则表达式模式

  2. 我将整个页面源代码放入正则表达式工具中,然后将正则表达式写入 return 与上面标识的相同字符串。看到正则表达式 here

  3. 单击右侧,匹配 1 组 1,以查看突出显示的与您在 BeautifulSoup 中看到的正则表达式 return 编辑的相同字符串。获取包含大小

    的相同字符串的两种不同方法

  1. 这就是我要检查的字符串,如JSON的结构。在 json 查看器中查看 here

  2. 你会注意到 JSON 与一些可能是动态的字典键非常嵌套,这意味着我需要编写可以遍历 JSON 的代码并使用某些更稳定的键来拉出可用的颜色,以及默认鞋颜色的尺寸和可用性

  3. JSON 查看器中有一个全部展开按钮。然后,您可以再次使用 Ctrl + F 搜索 38.5

10a) 我注意到尺码和可用性适用于默认鞋色

10b) 我还注意到,在 JSON 中,如果我从下拉列表中搜索其他颜色之一,我可以找到所列节目的每种颜色的 URI

  1. 我使用 Wolf 作为我的搜索词(因为我怀疑 JSON 中该词的匹配度较低)

您可以看到上面列出的其中一种替代颜色及其 URI

  1. 我访问了该 URI,并在我为默认白色鞋子所做的相同位置找到了该颜色的可用性和鞋码

  2. 我意识到我可以提出初始请求并获得默认的颜色和尺寸。从同一个请求中,提取其他颜色及其 URI

  3. 然后我可以向那些其他 URI 和 re-use 我现有的代码发出请求,以提取新颜色的 sizes/availability

  4. 这就是我创建 get_color_results() 函数的原因。这是从每个页面

    中提取尺寸和可用性的re-usable代码
  5. results 将 JSON 中的所有匹配项保存到我正在寻找的某些键,以导航到正确的位置以获取大小和可用性,以及当前颜色

  6. 此代码遍历JSON到达正确的位置提取我稍后要使用的数据

results = []
color = ""
for i in data["graphqlCache"]:
    if "ern:product" in i:
        if "product" in data["graphqlCache"][i]["data"]:
            if "name" in data["graphqlCache"][i]["data"]["product"]:
                results.append(data["graphqlCache"][i]["data"]["product"])
            if (
                color == ""
                and "color" in data["graphqlCache"][i]["data"]["product"]
            ):
                color = data["graphqlCache"][i]["data"]["product"]["color"]["name"]
  1. 以下从结果中提取尺寸和可用性:
{
    j["size"]: j["offer"]["stock"]["quantity"]
    for j in [i for i in results if "simples" in i][0]["simples"]
}
  1. 仅针对第一个请求,以下将其他鞋子颜色及其 URI 放入字典中以供稍后循环:
colors = {
    j["node"]["color"]["name"]: j["node"]["uri"]
    for j in [
        a
        for b in [
            i["family"]["products"]["edges"]
            for i in results
            if "family" in i
            if "products" in i["family"]
        ]
        for a in b
    ]
}
  1. 此位获取所有其他颜色及其可用性:
for k, v in colors.items():
    if k not in final:
        color, results = get_color_results(v)
        final[color] = {
            j["size"]: j["offer"]["stock"]["quantity"]
            for j in [i for i in results if "simples" in i][0]["simples"]
        }
  1. 自始至终,我用找到的颜色和相关的尺寸和可用性更新字典 final