【问题标题】:Scraping the "Compare Vintages" from Vivino从 Vivino 抓取“比较年份”
【发布时间】:2021-12-03 05:24:31
【问题描述】:

我正在尝试从 Vivino 抓取数据,到目前为止,我设法使用 API 并使用这篇文章从 json 文件中读取数据: https://stackoverflow.com/a/62224619/7575172

r = requests.get(
    "https://www.vivino.com/api/explore/explore",
    params = {
        "country_code": "DK",
        "country_codes[]":"fr",
        "currency_code":"DKK",
        "grape_filter":"varietal",
        "min_rating":"1",
        "order_by":"price",
        "order":"asc",
        "page": 1,
        "price_range_max":"500",
        "price_range_min":"0",
        "wine_type_ids[]":"1",
        
    },
    headers= {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0"
    }
)
results = [
    (
        t["vintage"]["wine"]["winery"]["name"], 
        f'{t["vintage"]["wine"]["name"]}',
        t['vintage']['year'],
        t['vintage']['wine']['region']['country']['name'],
        # t['vintage']['wine']['region']['name_en'],
        t['vintage']['wine']['style']['region']['name'],
        t["vintage"]["statistics"]["ratings_average"],
        t["vintage"]["statistics"]["ratings_count"],
        t['price']['amount']
    )
    for t in r.json()["explore_vintage"]["matches"]
]
dataframe = pd.DataFrame(results,columns=
                         ['Winery',
                          'Wine',
                          'Year',
                          'Country',
                          'Region',
                          'Rating',
                          'num_review',
                          'Price'])

# print(dataframe)
print(dataframe[['Winery','Year','Region','Rating','num_review','Price']])

但是,我在任何 json 文件中都找不到描述同一葡萄酒其他可用年份的数据。例如。我看的是 2019 年,但也有 2015-2020 年的数据。

我已使用 Firefox 中的网络监视器检查您打开以下页面时发送的其他 json 文件。但据我所知,关于可用年份总数的信息不存在?

可以在此处和图像中看到我要抓取的部分的示例: https://www.vivino.com/DK/en/pierre-amadieu-gigondas-romane-machotte-rouge/w/73846?ref=nav-search#vintageListSection

【问题讨论】:

  • 请使用与上图相关的代码版本进行更新,添加语言标签,例如python,并显示一些预期的输出行。理想情况下,至少有一个被检索到,一个丢失且需要。
  • @QHarr 我已经更新了代码和链接。
  • 该链接适用于不同的葡萄酒。你不是想比较 machotte-rouge 的年份吗?我不愿意在他们的数据库中搜索他们的所有数据。
  • @QHarr 是的,我现在更新了链接。但是请注意,确切的葡萄酒并不重要,但如果可能的话,我感兴趣的是一种通用方法来识别给定葡萄酒的其他年份(当我有葡萄酒 ID 时)。

标签: python web-scraping


【解决方案1】:

数据位于window.__PRELOADED_STATE__.winePageInformation对象下的javascript中,如下所示:

<script>
  window.__PRELOADED_STATE__ = ....
  window.__PRELOADED_STATE__.winePageInformation = { very long JSON here }
</script>

您可以使用正则表达式来提取它,结果似乎是有效的 JSON:

import requests
import re
import json

url = "https://www.vivino.com/DK/en/pierre-amadieu-gigondas-romane-machotte-rouge/w/73846"
r = requests.get(url,
headers= {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0"
})
# this gets the javascript object
res = re.search(r"^.*window\.__PRELOADED_STATE__\.winePageInformation\s*=\s*(.*});", r.text, re.MULTILINE)
print( r.text)
data = json.loads(res.group(1))

print("recommended vintages")
print(data["recommended_vintages"])

print("all vintages")
print(data["wine"]["vintages"])

【讨论】:

  • 这行得通,谢谢!只是出于好奇,您知道为什么从 GET 请求到 API 的 json 文件不像其他数据一样显示为 json 文件吗?我觉得这很奇怪。
  • @MalteJensen 我猜数据缓存在服务器端
  • 但有一件事,如果 json 文件中有任何分号,这会给我带来问题,所以我做了一个 hacky 解决方案来让它工作(我不喜欢正则表达式)。参见例如这个:vivino.com/DK/en/vidal-fleury-ventoux/w/1157565
  • @MalteJensen 我已经更新了这样的正则表达式(.*});
【解决方案2】:

伯特兰给了你最好的答案。也许奇怪的是,您访问的端点并未配置为允许您传入葡萄酒 ID 并取回所有年份。可用的参数是:

country_code, country_codes, currency_code, discount_prices, food_ids, 
grape_ids, grape_filter, max_rating, merchant_id, merchant_type, min_rating,
min_ratings_count, order_by, order, page, per_page, price_range_max, 
price_range_min, region_ids, wine_style_ids, wine_type_ids, winery_ids, 
vintage_ids, wine_years, excluding_vintage_id, wsa_year, top_list_filter

这些在JS文件https://www.vivino.com/packs/common-8f26f13b0ac53f391471.js中有详细说明。

您需要确定年份 ID 并将其传递给 API。

【讨论】:

    猜你喜欢
    • 2022-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-20
    • 1970-01-01
    • 2013-12-26
    相关资源
    最近更新 更多