美文网首页程序员
Scrapy入门:爬取动漫评论

Scrapy入门:爬取动漫评论

作者: chiiyu | 来源:发表于2020-07-12 11:33 被阅读0次

python 原创 转载注明出处 代码仅为教学演示 请勿恶意使用

Scrapy是一个功能强大的python爬虫框架,非常适合搭建工程。
Scrapy支持CSS和Xpath的语法,能够很方便地查找选取结点元素,从而提取结构化的数据。
同时,Scrapy支持非同步请求,也支持代理、cookie管理等高阶操作。因此,在上限和性能方面都相较另一个知名的包beautifulsoup更高。
对于一般数据提取的需求,通常只需在Spider类的基础上定义个人的爬虫即可完成目标。

文本主要展示使用scrapy爬取网站评论的过程,想要深入了解scrapy其他功能,可以阅读:官方教程 及相关文档。

命令行安装:

pip install scrapy

目标网站:myanimelist.net
任务:爬取用户的评分和评论
待提取项:用户名,评论提交时间,观看进度,整体评分,小项评分,文本评论
示例页面:灼眼的夏娜评论页

步骤:

  • 熟悉scrapy shell
scrapy shell
fetch("https://myanimelist.net/anime/355/Shakugan_no_Shana/reviews")
view(response) # 用默认浏览器打开网页

F12可进入开发者模式,观察网页的大致结构。
善用右键菜单Inspect Element,分析需要提取的数据结构。


image.png image.png

注意到用户的评论数据都在<div>标签下,可以通过class="borderDark"做筛选。几个需要提取的项,用户名、上传时间都比较好看出,在<td>标签下可以提取。一个难点是文本评论信息,网站对长评论进行了缩略,完整的评论需要通过read more展开

image.png
image.png

由于这里涉及到child string的遍历,直接用scrapySelectorList是比较无力的,考虑使用beautifulsoup

from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text)
reviews = soup.find_all("div", class_="borderDark") # 注意不能直接用class
# 查看第一个评论body内的string元素
reviews[0].text
image.png

可以看到前面所要提取的几个数据也在里面,因此在strings或者stripped_strings返回的迭代器列表化之后,就能够利用下标统一地提取列表中不同位置的数据。

list(reviews[0].stripped_strings)
image.png

例如时间是第1项,观看进度是第2项,用户名是第5项……依此类推,下面就可以开始建立具体的工程了。

  • 工程初始化
# 自行决定工作路径
scrapy startproject MyanimelistSpider
  • 创建爬虫脚本
cd MyanimelistSpider
scrapy genspider myanimelist "https://myanimelist.net/anime/355/Shakugan_no_Shana/reviews"
  • 定义Item类
# items.py
from scrapy.item import Item,Field
class MyanimelistReview(Item):
    username = Field()
    submission = Field()
    progress = Field()
    rating_overall = Field()
    rating_story = Field()
    rating_animation = Field()
    rating_sound = Field()
    rating_character = Field()
    rating_enjoyment = Field()
    helpful = Field()
    review = Field()
  • 定义Spider类
# spiders/myanimelist.py
import scrapy
from bs4 import BeautifulSoup
from WebSpiders.items import MyanimelistReview

class MyanimelistSpider(scrapy.Spider):
    name = "myanimelist"
    
    def start_requests(self):
        if not hasattr(self, "url"):
            self.url = ""
        url = self.url
        yield scrapy.Request(url, callback = self.get_review)
        
    def get_review(self, response):
        soup = BeautifulSoup(response.text)
        reviews = soup.find_all("div", class_="borderDark")
        for rev in reviews:
            extct = list(rev.stripped_strings)
            rating_startat = 12 if rev.find("i") else 11
            rating_endat = rating_startat + 11
            rating_overall,rating_story,rating_animation,rating_sound,rating_character,rating_enjoyment = extct[rating_startat:rating_endat:2]
            review = "\n".join(extct[rating_endat:][:-5])
            yield MyanimelistReview(
                    submission = extct[0],
                    progress = extct[1],
                    username = extct[4],
                    helpful = extct[8],
                    rating_overall = rating_overall,
                    rating_story = rating_story,
                    rating_animation = rating_animation,
                    rating_sound = rating_sound,
                    rating_character = rating_character,
                    rating_enjoyment = rating_enjoyment,
                    review = review
            )
        next_page = response.css("div.ml4 a[href*='reviews?p=']")
        if len(reviews) != 0:
            if next_page:
                yield response.follow(next_page[-1], callback=self.get_review)
  • 运行爬虫
scrapy crawl myanimelist -o shakugan_no_shana_reviews.json
  • 最终结果
    由 json 转化而成的 Excel 表格:


    image.png

数据到这里就提取完毕了,之后可以根据具体需求做分析。

相关文章

网友评论

    本文标题:Scrapy入门:爬取动漫评论

    本文链接:https://www.haomeiwen.com/subject/xhrgcktx.html