Scrapy:无法抓取应用程序商店评论页面

rmbxnbpk  于 2022-11-09  发布在  其他
关注(0)|答案(2)|浏览(131)

嗨,伙计们,我有一些问题,从应用程序商店从这个页面获取数据:应用程序商店评论apps.apple.com/us/app/mathy-cool-math-learner-games/id1476596747#see-all/reviews
首先,我想检索一个字符串,显示用户对应用程序的评分,这些评分位于一个figure标签中,标签class =“we-star-rating ember-view we-customer-review__rating we-star-rating--large”,其名称为attribute @aria-label。
app reviews page
下面是我的代码:

from scrapy import Selector
import requests

html = requests.get('https://apps.apple.com/us/app/mathy-cool-math-learner-games/id1476596747#see-all/reviews').content

sel = Selector(text = html)

sel.xpath('//figure[@class="we-star-rating ember-view we-customer-review__rating we-star-rating--large"]/@aria-label').extract()

但它只返回前3个匹配项:

['5 out of 5', '5 out of 5', '5 out of 5']

我想要的是检索所有评级可从所有评论在该页。
谁能给予我点提示吗?

kmbjn2e3

kmbjn2e31#

问题所在
前三个评论作为HTML的一部分加载,而其余的评论则由javascript加载,这就是为什么你只得到前三个结果的原因。
我不能完全确定这是否是你使用scrappy的全部代码,我很想知道你为什么选择scrappy的那部分。
所以处理javascript是现代网站抓取的一个重要部分。我不完全确定你是否主要使用scrapy来抓取网页。不过有一些选项可以用scrapy来处理javascript。

有关动态网页搜罗的信息

首先,我们知道现在的网站都是通过javascript调用HTTP请求来获取信息的,这被称为 AJAX 请求(异步Javascript和XHTML)。这会向API/服务器发出post或get HTTP请求,然后HTTP响应会返回信息。在这种情况下,他们会将3个结果预加载到HTML中,但在加载页面时会使用javascript请求其余的评论。
一般来说,有两种方法来处理面向javascript的网站。
1.重新设计HTTP请求--这是获取所需数据的最有效方法。您希望模仿javascript调用的HTTP请求。如果您能做到这一点,并且有时需要您发布头、参数和cookie,那么您就可以获取所需数据。
1.使用某种形式的浏览器自动化。Selenium是首选的软件包,尽管最初并不打算以这种方式使用。如果使用较大的数据集,它会很慢、效率低而且脆弱。

溶液

对于您的特定网站,您可以重新设计HTTP请求以获取所需的信息,这是理想的情况。
但是我怎么知道的呢?在chrome中你可以做的一件事就是关闭javascript。你必须检查页面,然后进入设置(点击页面最右边的三个点-〉更多工具-〉设置)。刷新页面,不要javascript。你会看到只有三条评论可以看。
要了解使用ChromeDev工具所发生的情况,信息量非常大。如果您右击并检查页面时转到网络选项卡,您将看到服务器发出的所有请求和响应。转到XHR选项卡,您将找到包含您想要的数据的请求。这里有一堆请求和响应。
请看下面的图片,我已经检查了页面,去网络和刷新页面。这记录了浏览器的请求和响应的活动。

你可以看到大约有6个请求,5个GET请求和一个POST请求。如果你点击每个请求,你会在右边看到一个弹出框,里面有请求数据、预览和响应。

在这里,我单击了第一个请求,然后单击了预览,您可以看到,如果您单击,将显示一些评论。
我可以看到,在HTTP请求中,该数据的偏移量为10,这意味着它正在获取接下来的10个请求。

所以我将改变偏移量,看看我是否可以得到前10个,然后第二个10个(在这个页面上有20个评论)。
无需手动输入参数和标头等...你可以将请求复制到一个CURL中,然后使用像curl.trillworks.com这样的网站将其转换成一个漂亮的python格式。

现在我们来看看预览数据,因为你需要用请求来处理它,你会得到一个JSON对象,你可以从HTTP get请求的接受部分得知它是application/json.
因此,在将此请求复制到curl.trillworks.com后,我们得到了以下内容。

编码示例

import requests

headers = {
    'Accept': 'application/json',
    'Referer': 'https://apps.apple.com/us/app/mathy-cool-math-learner-games/id1476596747',
    'Authorization': 'Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IldlYlBsYXlLaWQifQ.eyJpc3MiOiJBTVBXZWJQbGF5IiwiaWF0IjoxNTk2NTc1NTY4LCJleHAiOjE2MTIxMjc1Njh9.jnEuBNEVWhKGqI10W6dfhJFtYJtd74Nbu1NueZrPgYjU2K34LwXPQClcus8S9Jit5ayK5MOr0bIpcDx821RI4Q',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
}

params = (
    ('l', 'en-US'),
    ('offset', '1'),
    ('platform', 'web'),
    ('additionalPlatforms', 'appletv,ipad,iphone,mac'),
)

response = requests.get('https://amp-api.apps.apple.com/v1/catalog/us/apps/1476596747/reviews', headers=headers params=params)
response.json()

我在上面提到过,有时候你需要头和参数。你可以在这里尝试一下request get方法,看看是什么让你得到数据。在这种情况下,你需要参数和头。情况并不总是这样,因此你应该总是做一个简单的request.get(),而不需要任何东西。然后构建它。json()方法将json对象格式化为python字典,这样我们就可以轻松地访问数据。
现在,当我说查看预览时,提供了访问数据所需的键和值。有时数据可以嵌套得很深。在这种情况下,情况并非如此,所以我们现在考虑循环遍历这个字典以获得我们想要的所有数据。我们必须发出两个HTTP请求,一个偏移量为0,另一个偏移量为10,以获得完整的20星星评级。

最终代码示例

import requests

headers = {
    'Accept': 'application/json',
    'Referer': 'https://apps.apple.com/us/app/mathy-cool-math-learner-games/id1476596747',
    'Authorization': 'Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IldlYlBsYXlLaWQifQ.eyJpc3MiOiJBTVBXZWJQbGF5IiwiaWF0IjoxNTk2NTc1NTY4LCJleHAiOjE2MTIxMjc1Njh9.jnEuBNEVWhKGqI10W6dfhJFtYJtd74Nbu1NueZrPgYjU2K34LwXPQClcus8S9Jit5ayK5MOr0bIpcDx821RI4Q',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
}
for i in range(0,20,10):

    params = (
        ('l', 'en-US'),
        ('offset', f'{i}'),
        ('platform', 'web'),
        ('additionalPlatforms', 'appletv,ipad,iphone,mac'),
    )
    response = requests.get('https://amp-api.apps.apple.com/v1/catalog/us/apps/1476596747/reviews', params=params)
    data =  response.json()['data']
    for a in data:
        print(a['attributes']['rating'])

输出

5
5
5
5
5
...

代码解释

1.我们使用需要的头来进行请求(我设法获得数据没有它,但当试图获得所有数据,似乎想要的头,你可以玩这个虽然)
1.我们正在循环所需的参数,在本例中,我们希望偏移量为0,10。因此,我们使用range(0,20,10)来获取该值。使用每个参数,我们使用标头和这些特定参数发出HTTP get请求。
1.我们使用response.json()将响应转换为python字典。

1.如果你输出这个,我们可以看到大量的数据,我们需要在data键内,如下所示。如果你打印这个,你会得到下面的输出。
数据=响应.json()['数据']打印(数据)

输出

{'id': '5632394152',
 'type': 'user-reviews',
 'attributes': {'review': "I really like it. I have been using a memory trainer, but this one is a little bit more fun. I had to learn my skills the hard way so to speak, but it is really fun! I can't wait to buy it again! 😁🤓",
  'rating': 5,
  'title': 'Cow force than',
  'date': '2020-03-08T11:37:29Z',
  'userName': 'MY VICELER',
  'isEdited': False}}

1.所以你可以看到,我们需要的数据实际上在attributes键后面,然后是rating键,因此我们需要遍历response.json()['data']),并访问一个['attribute']['value'],它给出了输出。

相关问题