【问题标题】:requests-html not finding page elementrequests-html 找不到页面元素
【发布时间】:2019-07-05 21:24:42
【问题描述】:

所以我试图导航到这个网址:https://www.instacart.com/store/wegmans/search_v3/horizon%201%25 并使用 item-name item-row 类从 div 中抓取数据。但是有两个主要问题,第一个是 instacart.com 需要登录才能访问该 url,第二个是大部分页面是用 javascript 生成的。

我相信我已经解决了第一个问题,因为我的session.post(...) 收到了 200 响应代码。我也很确定r.html.render() 应该通过在我抓取它之前渲染 javascript 生成的 html 来解决第二个问题。不幸的是,我代码中的最后一行只返回一个空列表,尽管 selenium 获取这个元素没有问题。有谁知道为什么这不起作用?

from requests_html import HTMLSession
from bs4 import BeautifulSoup
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
session = HTMLSession()
res1 = session.get('http://www.instacart.com', headers=headers)
soup = BeautifulSoup(res1.content, 'html.parser')
token = soup.find('meta', {'name': 'csrf-token'}).get('content')
data = {"user": {"email": "alexanderjbusch@gmail.com", "password": "password"},
        "authenticity_token": token}
response = session.post('https://www.instacart.com/accounts/login', headers=headers, data=data)
print(response)
r = session.get("https://www.instacart.com/store/wegmans/search_v3/horizon%201%25", headers=headers)
r.html.render()
print(r.html.xpath("//div[@class='item-name item-row']"))

【问题讨论】:

  • 登录后,尝试使用this link 获取您要查找的项目。
  • 我不明白。那个链接是干什么用的?如何使用它来获取商品数据?

标签: python cookies web-scraping python-requests-html


【解决方案1】:

使用 requests 模块和 BeautifulSoup 登录后,您可以使用我已经在评论中建议的链接来解析 json 中可用的所需数据。以下脚本应为您提供名称、数量、价格和相关产品的链接。您只能使用以下脚本获得 21 个产品。在这个 json 内容中有一个分页选项。您可以通过使用该分页来获得所有产品。

import json
import requests
from bs4 import BeautifulSoup

baseurl = 'https://www.instacart.com/store/'
data_url = "https://www.instacart.com/v3/retailers/159/module_data/dynamic_item_lists/cart_starters/storefront_canonical?origin_source_type=store_root_department&tracking.page_view_id=b974d56d-eaa4-4ce2-9474-ada4723fc7dc&source=web&cache_key=df535d-6863-f-1cd&per=30"

data = {"user": {"email": "alexanderjbusch@gmail.com", "password": "password"},
        "authenticity_token": ""}
headers = {
    'user-agent':'Mozilla/5.0',
    'x-requested-with': 'XMLHttpRequest'
}
with requests.Session() as s:

    res = s.get('https://www.instacart.com/',headers={'user-agent':'Mozilla/5.0'})
    soup = BeautifulSoup(res.text, 'lxml')
    token = soup.select_one("[name='csrf-token']").get('content')

    data["authenticity_token"] = token

    s.post("https://www.instacart.com/accounts/login",json=data,headers=headers)
    resp = s.get(data_url, headers=headers)

    for item in resp.json()['module_data']['items']:
        name = item['name']
        quantity = item['size']
        price = item['pricing']['price']
        product_page = baseurl + item['click_action']['data']['container']['path']
        print(f'{name}\n{quantity}\n{price}\n{product_page}\n')

部分输出:

SB Whole Milk
1 gal
$3.90
https://www.instacart.com/store/items/item_147511418

Banana
At $0.69/lb
$0.26
https://www.instacart.com/store/items/item_147559922

Yellow Onion
At $1.14/lb
$0.82
https://www.instacart.com/store/items/item_147560764

【讨论】:

  • 好的,这是朝着正确方向迈出的一大步,但在我将此标记为答案之前,我有两个问题。首先,你是怎么找到这个url的,所以我知道以后如果我想抓取其他类似的网站怎么找到?第二,如何从特定商店获取特定商品的数据?例如,来自 wegmans 的 Horizo​​n 1% 牛奶?我是否要更改基本网址或其他内容?
  • 在尝试抓取任何网站之前,您需要了解请求是如何发送的,您可以通过打开 chrome 开发工具了解这些请求。打开开发工具后,找到网络选项卡,然后选择 xhr 选项卡,然后重新加载页面。重新加载页面后,您可以在左侧窗格中看到几个 url 执行不同的网络活动。只需选择包含所需数据的正确 url,然后单击它。现在您应该在右窗格中看到有关该 url 的大量信息。您只需将所需的 url 替换为 data_url。
  • 顺便说一句,如果您要放置的 url 具有不同的 json 结构,那么您需要将脚本从 for loop 修改到最后以满足您的需要。谢谢。
猜你喜欢
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 2018-01-24
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多