Scrapy:无法抓取应用商店评论页面
Scrapy: Can't Crawling App store Reviews Page
大家好,我在从应用商店获取此页面的数据时遇到了一些问题:
app store reviewshttps://apps.apple.com/us/app/mathy-cool-math-learner-games/id1476596747#see-all/reviews
我想首先检索一个字符串,显示用户对应用程序的评分。它们位于带有 class = "we-star-rating ember-view we-customer-review__rating we-star-rating--large" 的图形标签内,并且是属性 @aria 的名称-标签。
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']
我想要的是从该页面的所有评论中检索所有可用的评分。
有人可以给我一些线索吗?
问题
前三个评论作为 HTML 的一部分加载,但其余评论由 javascript 加载。这就是为什么您只获得前三个结果的原因。
我不完全确定这是否是您使用 scrapy 的全部代码。我很想知道你为什么选择 scrapy 的那个部分。
所以处理 javascript 是网络抓取现代网站的重要组成部分。我不完全确定您是否主要使用 scrapy 进行网络抓取。不过,有一些选项可以用 scrapy 处理 javascript。
有关动态网页抓取的信息
首先知道这些天的网站会动态获取信息,使用 javascript 调用 HTTP 请求,称为 AJAX 请求(异步 Javascript 和 XHTML ).这会向 API/server 发出 post 或获取 HTTP 请求,并且该 HTTP 响应返回信息。在这种情况下,他们已将 3 个结果预加载到 HTML 中,但要求在使用 javascript.
加载页面时提供其余评论
一般来说,有两种方法可以处理javascript导向的网站。
- Re-engineer HTTP 请求 - 这是获取所需数据的最有效方式。您想要模仿 javascript 正在调用的这些 HTTP 请求。如果你能做到这一点,这有时需要你 post headers、参数和 cookie,那么你可以获得你想要的数据。
- 使用某种形式的浏览器自动化。 Selenium 是首选包,尽管最初并不打算以这种方式使用。如果使用更大的数据集,它会缓慢、低效且脆弱。
解决方案
对于您的特定网站,您可以 re-engineer HTTP 请求来获取您想要的信息。这是最理想的情况。
但我怎么知道的?好吧,您可以在 chrome 中做的一件事就是关闭 javascript。您必须检查页面并转到设置(单击页面右侧的三个点 -> 更多工具 -> 设置)。没有javascript刷新页面。你会看到只有三个评论可以看。
使用 ChromeDev 工具了解正在发生的事情非常有用。如果您在 right-click 时转到网络选项卡并检查页面,您将看到服务器发出的所有请求和响应。转到 XHR 选项卡,您会在其中找到包含所需数据的请求。这里有一堆请求和响应。
见下图,我检查了页面,上网并刷新了页面。这记录了浏览器的请求和响应的activity。
您可以看到大约有 6 个请求,5 个 GET 请求和一个 POST 请求。如果您单击每个请求,您将在右侧看到一个弹出框,其中包含请求数据、预览和响应。
这里我点击了第一个请求,我点击了预览,如果你点击通过,你可以看到有一些评论。
我可以在该数据的 HTTP 请求中看到偏移量为 10,这意味着它正在抓取接下来的 10 个请求。
所以我要改变这个偏移量,看看我是否可以得到前 10 个,然后是第二个 10 个(此页面上有 20 条评论)。
无需手动输入参数和headers等...您可以将请求复制到CURL中。然后可以使用 curl.trillworks.com
之类的网站将其转换为漂亮的 python 格式。
现在查看预览数据是值得的,因为您将不得不使用请求来处理它。您将以 JSON object 结束,您可以从 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()
我上面提到有时你需要headers和参数。您可以在这里尝试使用请求获取方法,看看是什么让您获取数据。在这种情况下,您需要参数和 headers。情况并非总是如此,因此您应该始终不带任何内容地执行简单的 request.get()
,然后构建它。 json()
方法将 json object 格式化为 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
...
代码说明
我们使用发出请求所需的 headers(我设法在没有它的情况下获取数据,但在尝试获取所有数据时,似乎需要 headers ,你可以玩这个
我们正在循环所需的参数,在这种情况下我们希望偏移量为 0、10。所以我们使用 range(0,20,10)
来得到它。对于每个参数,我们使用 headers 和那些特定参数发出 HTTP get 请求。
我们使用 response.json()
将响应转换为 python 字典
如果你输出这个我们可以看到很多数据,我们需要在 data
键内,如下所示。如果你打印这个,你会得到下面的输出。
数据=response.json()['data']
打印(数据)
输出
{'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}}
- 所以你可以看到其实我们要的数据在
attributes
键后面,然后是rating
键。因此,我们想遍历 response.json()['data'])
并访问 a['attribute']['value'],这给了我们输出。
您可以使用
- http://itunes.apple.com/lookup?id=APPID
- https://itunes.apple.com/rss/customerreviews/id=APPID/sortBy=mostRecent/json
这些是 Apple 提供的 API,它们比直接抓取网站要好得多。
大家好,我在从应用商店获取此页面的数据时遇到了一些问题: app store reviewshttps://apps.apple.com/us/app/mathy-cool-math-learner-games/id1476596747#see-all/reviews
我想首先检索一个字符串,显示用户对应用程序的评分。它们位于带有 class = "we-star-rating ember-view we-customer-review__rating we-star-rating--large" 的图形标签内,并且是属性 @aria 的名称-标签。
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']
我想要的是从该页面的所有评论中检索所有可用的评分。
有人可以给我一些线索吗?
问题
前三个评论作为 HTML 的一部分加载,但其余评论由 javascript 加载。这就是为什么您只获得前三个结果的原因。
我不完全确定这是否是您使用 scrapy 的全部代码。我很想知道你为什么选择 scrapy 的那个部分。
所以处理 javascript 是网络抓取现代网站的重要组成部分。我不完全确定您是否主要使用 scrapy 进行网络抓取。不过,有一些选项可以用 scrapy 处理 javascript。
有关动态网页抓取的信息
首先知道这些天的网站会动态获取信息,使用 javascript 调用 HTTP 请求,称为 AJAX 请求(异步 Javascript 和 XHTML ).这会向 API/server 发出 post 或获取 HTTP 请求,并且该 HTTP 响应返回信息。在这种情况下,他们已将 3 个结果预加载到 HTML 中,但要求在使用 javascript.
加载页面时提供其余评论一般来说,有两种方法可以处理javascript导向的网站。
- Re-engineer HTTP 请求 - 这是获取所需数据的最有效方式。您想要模仿 javascript 正在调用的这些 HTTP 请求。如果你能做到这一点,这有时需要你 post headers、参数和 cookie,那么你可以获得你想要的数据。
- 使用某种形式的浏览器自动化。 Selenium 是首选包,尽管最初并不打算以这种方式使用。如果使用更大的数据集,它会缓慢、低效且脆弱。
解决方案
对于您的特定网站,您可以 re-engineer HTTP 请求来获取您想要的信息。这是最理想的情况。
但我怎么知道的?好吧,您可以在 chrome 中做的一件事就是关闭 javascript。您必须检查页面并转到设置(单击页面右侧的三个点 -> 更多工具 -> 设置)。没有javascript刷新页面。你会看到只有三个评论可以看。
使用 ChromeDev 工具了解正在发生的事情非常有用。如果您在 right-click 时转到网络选项卡并检查页面,您将看到服务器发出的所有请求和响应。转到 XHR 选项卡,您会在其中找到包含所需数据的请求。这里有一堆请求和响应。
见下图,我检查了页面,上网并刷新了页面。这记录了浏览器的请求和响应的activity。
您可以看到大约有 6 个请求,5 个 GET 请求和一个 POST 请求。如果您单击每个请求,您将在右侧看到一个弹出框,其中包含请求数据、预览和响应。
这里我点击了第一个请求,我点击了预览,如果你点击通过,你可以看到有一些评论。
我可以在该数据的 HTTP 请求中看到偏移量为 10,这意味着它正在抓取接下来的 10 个请求。
所以我要改变这个偏移量,看看我是否可以得到前 10 个,然后是第二个 10 个(此页面上有 20 条评论)。
无需手动输入参数和headers等...您可以将请求复制到CURL中。然后可以使用 curl.trillworks.com
之类的网站将其转换为漂亮的 python 格式。
现在查看预览数据是值得的,因为您将不得不使用请求来处理它。您将以 JSON object 结束,您可以从 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()
我上面提到有时你需要headers和参数。您可以在这里尝试使用请求获取方法,看看是什么让您获取数据。在这种情况下,您需要参数和 headers。情况并非总是如此,因此您应该始终不带任何内容地执行简单的 request.get()
,然后构建它。 json()
方法将 json object 格式化为 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
...
代码说明
我们使用发出请求所需的 headers(我设法在没有它的情况下获取数据,但在尝试获取所有数据时,似乎需要 headers ,你可以玩这个
我们正在循环所需的参数,在这种情况下我们希望偏移量为 0、10。所以我们使用
range(0,20,10)
来得到它。对于每个参数,我们使用 headers 和那些特定参数发出 HTTP get 请求。我们使用
将响应转换为 python 字典response.json()
如果你输出这个我们可以看到很多数据,我们需要在
data
键内,如下所示。如果你打印这个,你会得到下面的输出。数据=response.json()['data'] 打印(数据)
输出
{'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}}
- 所以你可以看到其实我们要的数据在
attributes
键后面,然后是rating
键。因此,我们想遍历response.json()['data'])
并访问 a['attribute']['value'],这给了我们输出。
您可以使用
- http://itunes.apple.com/lookup?id=APPID
- https://itunes.apple.com/rss/customerreviews/id=APPID/sortBy=mostRecent/json
这些是 Apple 提供的 API,它们比直接抓取网站要好得多。