这里的主要内容是我们在按下“下一步按钮”后发出的请求。我们应该用 SiteID、endCursor 和 startCursor 更新它(我们也可以更新方向)。
我们可以在页面的源代码中找到所有必要的参数。在“root.RottenTomatoes.context.movieReview”下
我们可以用正则表达式抓取代码并制作一个python字典来轻松获取所有参数。
regex = r'root\.RottenTomatoes\.context\.movieReview = (.*?);'
movie_review_data = re.findall(regex, tomatoes_scripts)[0]
movie_review_data_dict = json.loads(movie_review_data)
然后我们获取 SiteID、endCursor 和 endCursor
movie_id = movie_review_data_dict.get('movieId')
next_page = movie_review_data_dict.get('pageInfo').get('hasNextPage')
end_cursor = movie_review_data_dict.get('pageInfo').get('endCursor')
我们能够从页面中获取第一个 cmets,并使用我们使用参数构建的特殊 URL 发出下一个请求。响应是一个 JSON 对象,我们将其作为 Python 字典(其中包含我们为下一页更新的参数)。
之后,我们循环我们的方法并从字典中获取所有必要的字段。我提供了完整的代码,但被告知它可以工作,但它是一个草稿,当然,我们必须使用最好的 Scrapy 实践,如 Items、ItemLoaders,为 generate_review_url 函数创建一个单独的文件等。代码是即时编写的,并且展示主要思想并有效
import scrapy
import re
import json
def generate_review_url(movie_id,
end_cursor,
start_cursor=''):
return f'https://www.rottentomatoes.com/napi/movie/{movie_id}'\
f'/reviews/user?direction=next&'\
f'endCursor={end_cursor}&startCursor={start_cursor}'
class ReviewsSpider(scrapy.Spider):
name = 'reviews'
allowed_domains = ['rottentomatoes.com']
start_urls = [
'https://www.rottentomatoes.com/m/ghostbusters/reviews?type=user'
]
def parse(self, response):
tomatoes_scripts = response.xpath(
'//script[contains(text(), "function (root)")]/text()'
).get()
regex = r'root\.RottenTomatoes\.context\.movieReview = (.*?);'
movie_review_data = re.findall(regex, tomatoes_scripts)[0]
movie_review_data_dict = json.loads(movie_review_data)
movie_id = movie_review_data_dict.get('movieId')
next_page = movie_review_data_dict.get('pageInfo').get('hasNextPage')
end_cursor = movie_review_data_dict.get('pageInfo').get('endCursor')
reviews = response.xpath('//ul[@class="audience-reviews"]/li')
for review in reviews:
yield {
'review': review.xpath(
'.//p[contains(@class, "audience-reviews__review")]/text()'
).get()
}
if next_page:
yield scrapy.Request(
url=generate_review_url(movie_id, end_cursor),
callback=self.parse_special_response,
meta={'movie_id': movie_id}
)
def parse_special_response(self, response):
response_dict = json.loads(response.body)
reviews = response_dict.get('reviews')
for review in reviews:
yield {
'review': review.get('review')
}
movie_id = response.meta.get('movie_id')
next_page = response_dict.get('pageInfo').get('hasNextPage')
end_cursor = response_dict.get('pageInfo').get('endCursor')
start_cursor = response_dict.get('pageInfo').get('startCursor')
if next_page:
yield scrapy.Request(
url=generate_review_url(movie_id, end_cursor, start_cursor),
callback=self.parse_special_response,
meta={'movie_id': movie_id}
)
regEx 的解决方案对我来说看起来有点“脏”,也没有任何异常控制等。欢迎改进 =)
用户评论中似乎有 25 万多条来自用户的评论。当我收集到 11k 条评论时,我停止了脚本。我也测试了这部电影https://www.rottentomatoes.com/m/pg_psycho_goreman/reviews?type=user 并收集了 46 条所有相关的评论 =)