geturl
import requests
import json
# GraphQL请求URL
url = "https://www.chewy.com/api/pdp/graphql"
# 请求头
headers = {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"apollo-require-preflight": "true",
"content-type": "application/json",
"origin": "https://www.chewy.com",
"priority": "u=1, i",
"referer": "https://www.chewy.com/jespet-4-wheel-pet-stroller-maroon-36/dp/211142",
"sec-ch-ua": '"Not A(Brand";v="8", "Chromium";v="132", "Microsoft Edge";v="132"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0",
"x-dtpc": "3$469704714_962h77vCVHABIHTOUWKPNCUNIGUOHUFUDJKVQGB-0e0"
}
# GraphQL查询
query = """
mutation PDP_AddToCart($input: AddToCartInput!) {
addToCart(input: $input) {
updated {
...PDP_Cart__CartItem
__typename
}
cart {
...PDP_Cart
__typename
}
__typename
}
}
fragment PDP_Cart__CartItem on CartItem {
id
item {
...PDP_Cart__Item
__typename
}
partNumber
price
quantity
subtotal
customizedAttributes {
personalizedThumbnailUrl
__typename
}
__typename
}
fragment PDP_Cart__Item on Item {
id
isVetDiet
isPrescription
...PDP_SmartShelf__AddedItem
...PDP_Analytics__Item
__typename
}
fragment PDP_SmartShelf__AddedItem on Item {
fullImage {
url(autoCrop: true, square: 144)
__typename
}
entryID
partNumber
name
product {
name
id
manufacturerName
__typename
}
isPrescription
isGiftCard
isBundleMultiSku
isPersonalized
is3DCustomizable
bundleTitle
offerPrice
__typename
}
fragment PDP_Analytics__Item on Item {
id
entryID
advertisedPrice
definingAttributeValues: attributeValues(
usage: [DEFINING]
includeEnsemble: true
) {
...PDP_Analytics__AttributeValue
__typename
}
is3DCustomizable
isPersonalized
is3DCustomizable
images {
...PDP_CarouselImage
meta: url(maxHeight: 630)
metaLarge: url(square: 1800, autoCrop: true)
__typename
}
shelterImages: images {
main: url(autoCrop: true, square: 600)
__typename
}
parentCatalogGroupId
name
onSpecial
partNumber
product {
...PDP_Analytics__Product
__typename
}
strikeThroughPrice
isGiftCard
isAutoshipAllowed
inStock
isPrescription
masterCatalogIdentifier
__typename
}
fragment PDP_Analytics__AttributeValue on AttributeValue {
id
value
attribute {
id
name
__typename
}
__typename
}
fragment PDP_CarouselImage on Image {
__typename
thumbnail: url(autoCrop: true, square: 108)
main: url(autoCrop: true, sideLongest: 600)
magnified: url(autoCrop: true, sideLongest: 1200)
magnifiedModal: url(autoCrop: true, sideLongest: 1800)
}
fragment PDP_Analytics__Product on Product {
id
entryID
manufacturerName
name
partNumber
slug
rating
ratingCount
breadcrumbs {
...Breadcrumb
__typename
}
__typename
}
fragment Breadcrumb on Breadcrumb {
id
name
url
__typename
}
fragment PDP_Cart on Cart {
id
subtotal
totalQuantity
freeShippingAmount
freeShippingEligibleAmount
freeShippingThresholdAmount
shippingPrice
hasGiftCard
__typename
}
"""
# 请求体
payload = {
"operationName": "PDP_AddToCart",
"variables": {
"input": {
"items": [
{
"partNumber": "1060313",
"quantity": 1,
"attributes": {}
}
]
}
},
"extensions": {},
"query": query
}
try:
# 发送POST请求
response = requests.post(url, headers=headers, json=payload)
# 检查响应状态码
response.raise_for_status()
# 打印响应内容
print(json.dumps(response.json(), indent=2, ensure_ascii=False))
except requests.exceptions.RequestException as e:
print(f"请求发生错误: {e}")
except json.JSONDecodeError as e:
print(f"JSON解析错误: {e}")
print(f"JSON解析错误: {e}")
获取商品信息
import requests
import json
import csv
import time
from datetime import datetime
# GraphQL请求URL
url = "https://www.chewy.com/api/pdp/graphql"
# 请求头
headers = {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"apollo-require-preflight": "true",
"content-type": "application/json",
"origin": "https://www.chewy.com",
"priority": "u=1, i",
"referer": "https://www.chewy.com/jespet-4-wheel-pet-stroller-maroon-36/dp/211142",
"sec-ch-ua": '"Not A(Brand";v="8", "Chromium";v="132", "Microsoft Edge";v="132"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0",
"x-dtpc": "3$469704714_962h77vCVHABIHTOUWKPNCUNIGUOHUFUDJKVQGB-0e0"
}
# GraphQL查询 - 获取产品详情
product_query = """
query PDP_SmartShelf($partNumber: String!, $promotionId: String, $includePetsAndClinics: Boolean!, $loyaltyFeaturesEnabled: Boolean!) {
cart {
id
...PDP_SmartShelf__Cart
items {
...PDP_ItemCartUpdateInfo
__typename
}
__typename
}
smartShelf(partNumber: $partNumber, promotionId: $promotionId) {
currentItem {
id
...PDP_SmartShelf__Item
images {
url
thumbnail: url(autoCrop: true, square: 108)
main: url(autoCrop: true, sideLongest: 600)
magnified: url(autoCrop: true, sideLongest: 1200)
magnifiedModal: url(autoCrop: true, sideLongest: 1800)
__typename
}
__typename
}
promotion {
...PDP_SmartShelf__Promotion
__typename
}
promotionItemsInCartCount
__typename
}
userData {
membershipStatus @include(if: $loyaltyFeaturesEnabled)
__typename
}
currentUser {
clinicOrgs {
...PDP_ClinicOrgs @include(if: $includePetsAndClinics)
__typename
}
__typename
}
}
fragment PDP_SmartShelf__Cart on Cart {
...PDP_Cart
__typename
}
fragment PDP_Cart on Cart {
id
subtotal
totalQuantity
freeShippingAmount
freeShippingEligibleAmount
freeShippingThresholdAmount
shippingPrice
hasGiftCard
__typename
}
fragment PDP_ItemCartUpdateInfo on CartItem {
cartId
quantity
item {
id
partNumber
__typename
}
__typename
}
fragment PDP_SmartShelf__Item on Item {
id
description
fullImage {
url(autoCrop: true, square: 400)
__typename
}
freeShippingThreshold
name
advertisedPrice
partNumber
mapEnforced
mapEnforcedText
mapSavings
entryID
isPrescription
isPersonalized
product {
id
entryID
manufacturerName
rating
ratingCount
slug
petType: attributes(identifier: "PetType") {
values {
id
value
__typename
}
__typename
}
definingAttributes: attributes(usage: [DEFINING], includeEnsemble: true) {
id
name
values {
id
value
__typename
}
__typename
}
__typename
}
minimumPetWeights {
name
id
identifier
values {
id
value
__typename
}
__typename
}
maximumPetWeights {
name
id
identifier
values {
id
value
__typename
}
__typename
}
strikeThroughPrice
__typename
}
fragment PDP_SmartShelf__Promotion on Promotion {
id
condition
helperText
isSmartshelfEligible
longDescription
name
promotionType
reward
rewardType
shortDescription
__typename
}
fragment PDP_ClinicOrgs on ClinicOrg {
name
phoneNumber
postalCode
communicationPreference
id
__typename
}
"""
def get_product_data(part_number):
# 获取产品详情的请求
payload = {
"operationName": "PDP_SmartShelf",
"variables": {
"partNumber": part_number,
"promotionId": "11309",
"includePetsAndClinics": False,
"loyaltyFeaturesEnabled": True
},
"extensions": {},
"query": product_query
}
try:
response = requests.post(url, headers=headers, json=payload)
print(f"Response status code: {response.status_code}")
print(f"Response headers: {response.headers}")
response.raise_for_status()
data = response.json()
print(f"Response data: {json.dumps(data, indent=2)}")
return data
except Exception as e:
print(f"Error fetching data for part number {part_number}: {e}")
if hasattr(e, 'response') and e.response is not None:
print(f"Error response: {e.response.text}")
return None
def get_variant_partnumbers(product_data):
"""从产品数据中提取所有颜色变体的partnumber"""
variant_partnumbers = []
if not product_data or 'data' not in product_data:
return variant_partnumbers
try:
# 从购物车数据中获取其他颜色变体的partnumber
cart_items = product_data.get('data', {}).get('cart', {}).get('items', [])
for item in cart_items:
if item.get('item', {}).get('partNumber'):
variant_partnumbers.append(item['item']['partNumber'])
except Exception as e:
print(f"Error getting variant partnumbers: {e}")
return variant_partnumbers
def get_color_variants(product_data):
"""从产品数据中提取所有颜色变体信息"""
variants = []
if not product_data or 'data' not in product_data:
return variants
try:
current_item = product_data['data']['smartShelf']['currentItem']
if current_item and current_item.get('product'):
# 获取当前颜色和partnumber
current_partnumber = current_item['partNumber']
current_color = None
# 获取所有颜色变体信息
defining_attrs = current_item['product'].get('definingAttributes', [])
for attr in defining_attrs:
if attr['name'] == 'Color':
current_color = attr['values'][0]['value']
# 获取所有颜色变体
for value in attr['values']:
if value['value'] != current_color:
variants.append({
'color': value['value'],
'partnumber': value['id'] # 使用ID作为partnumber
})
break
# 如果在购物车中有其他变体,也添加进去
cart_items = product_data.get('data', {}).get('cart', {}).get('items', [])
for item in cart_items:
if item.get('item', {}).get('partNumber') and item['item']['partNumber'] != current_partnumber:
variants.append({
'partnumber': item['item']['partNumber']
})
except Exception as e:
print(f"Error getting color variants: {e}")
return variants
def convert_to_shopify_format(product_data):
if not product_data or 'data' not in product_data or not product_data['data'].get('smartShelf', {}).get('currentItem'):
return None
try:
item = product_data['data']['smartShelf']['currentItem']
product = item['product']
# Get pet types
pet_types = []
if 'petType' in product:
for pet_type in product['petType']:
for value in pet_type['values']:
pet_types.append(value['value'])
# Get attributes as tags
tags = []
if 'definingAttributes' in product:
for attr in product['definingAttributes']:
if attr['name'] and attr['values']:
for value in attr['values']:
tags.append(f"{attr['name']}:{value['value']}")
# Add rating and rating count to tags if available
if product.get('rating') and product.get('ratingCount'):
tags.append(f"Rating:{product['rating']}")
tags.append(f"Reviews:{product['ratingCount']}")
# Add pet types to tags
tags.extend(pet_types)
# 获取所有颜色变体
colors = []
if 'definingAttributes' in product:
for attr in product['definingAttributes']:
if attr['name'] == 'Color':
colors = [value['value'] for value in attr['values']]
break
# 如果没有找到颜色变体,则至少包含当前颜色
if not colors:
colors = [""]
result_rows = []
# 获取所有图片URL
images = item.get('images', [])
# 为每个颜色创建一行数据
for color in colors:
# 创建基础数据
row_data = {
"Handle": f"chewy-{item['partNumber']}",
"Title": item['name'],
"Body (HTML)": item['description'] if item.get('description') else "",
"Vendor": product['manufacturerName'],
"Type": " > ".join(pet_types) if pet_types else "Pet Supplies",
"Tags": ", ".join(tags),
"Published": "TRUE",
"Option1 Name": "Color",
"Option1 Value": color,
"Option2 Name": "",
"Option2 Value": "",
"Option3 Name": "",
"Option3 Value": "",
"Variant SKU": f"{item['partNumber']}",
"Variant Grams": "0",
"Variant Inventory Tracker": "shopify",
"Variant Inventory Qty": "10",
"Variant Inventory Policy": "deny",
"Variant Fulfillment Service": "manual",
"Variant Price": item['advertisedPrice'].replace('$', '') if item.get('advertisedPrice') else "",
"Variant Compare At Price": item['strikeThroughPrice'].replace('$', '') if item.get('strikeThroughPrice') else "",
"Variant Requires Shipping": "TRUE",
"Variant Taxable": "TRUE",
"Variant Barcode": "",
"Image Position": "",
"Image Alt Text": item['name'],
"Gift Card": "FALSE",
"SEO Title": item['name'],
"SEO Description": item['description'] if item.get('description') else "",
"Google Shopping / Google Product Category": "Pet Supplies",
"Google Shopping / Gender": "",
"Google Shopping / Age Group": "",
"Google Shopping / MPN": item['partNumber'],
"Google Shopping / AdWords Grouping": "",
"Google Shopping / AdWords Labels": "",
"Google Shopping / Condition": "New",
"Google Shopping / Custom Product": "",
"Google Shopping / Custom Label 0": "",
"Google Shopping / Custom Label 1": "",
"Google Shopping / Custom Label 2": "",
"Google Shopping / Custom Label 3": "",
"Google Shopping / Custom Label 4": "",
"Variant Image": "",
"Variant Weight Unit": "g",
"Variant Tax Code": "",
"Cost per item": "",
"Status": "active"
}
# 只为第一个颜色添加图片信息
if color == colors[0] and images:
# 第一行包含完整的产品信息和第一张图片
row_data["Image Src"] = images[0].get('magnifiedModal', '')
row_data["Image Position"] = "1"
result_rows.append(row_data)
# 后续行只包含图片信息
for i, image in enumerate(images[1:], 2):
image_row = {
"Handle": row_data["Handle"],
"Image Src": image.get('magnifiedModal', ''),
"Image Position": str(i),
"Image Alt Text": row_data["Image Alt Text"]
}
result_rows.append(image_row)
else:
# 其他颜色只添加基本信息,不包含图片
result_rows.append(row_data)
return result_rows
except Exception as e:
print(f"Error converting data to Shopify format: {e}")
print(f"Product data: {json.dumps(product_data, indent=2)}")
return None
def main():
# 读取partnumbers
with open('chewy_partnumbers.txt', 'r') as f:
part_numbers = [line.strip() for line in f if line.strip()]
# 准备CSV文件
fieldnames = ["Handle", "Title", "Body (HTML)", "Vendor", "Type", "Tags", "Published",
"Option1 Name", "Option1 Value", "Option2 Name", "Option2 Value",
"Option3 Name", "Option3 Value", "Variant SKU", "Variant Grams",
"Variant Inventory Tracker", "Variant Inventory Qty", "Variant Inventory Policy",
"Variant Fulfillment Service", "Variant Price", "Variant Compare At Price",
"Variant Requires Shipping", "Variant Taxable", "Variant Barcode",
"Image Src", "Image Position", "Image Alt Text", "Gift Card",
"SEO Title", "SEO Description", "Google Shopping / Google Product Category",
"Google Shopping / Gender", "Google Shopping / Age Group", "Google Shopping / MPN",
"Google Shopping / AdWords Grouping", "Google Shopping / AdWords Labels",
"Google Shopping / Condition", "Google Shopping / Custom Product",
"Google Shopping / Custom Label 0", "Google Shopping / Custom Label 1",
"Google Shopping / Custom Label 2", "Google Shopping / Custom Label 3",
"Google Shopping / Custom Label 4", "Variant Image", "Variant Weight Unit",
"Variant Tax Code", "Cost per item", "Status"]
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_file = f'chewy_products_{timestamp}.csv'
with open(output_file, 'w', newline='', encoding='utf-8-sig') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for part_number in part_numbers:
print(f"\nProcessing part number: {part_number}")
product_data = get_product_data(part_number)
if product_data and product_data.get('data', {}).get('smartShelf', {}).get('currentItem'):
shopify_data_rows = convert_to_shopify_format(product_data)
if shopify_data_rows:
for row in shopify_data_rows:
writer.writerow(row)
time.sleep(2)
print(f"\nCompleted! Results saved to {output_file}")
if __name__ == "__main__":
main()