Scrapy 豆瓣爬虫

安装

下列的安装步骤假定您已经安装好下列程序:

您可以使用pip来安装Scrapy(推荐使用pip来安装Python package).

使用pip安装:

1
pip install Scrapy

创建项目

创建一个scrapy爬虫项目和一般的python框架一样,使用以下命令即可快速创建一个项目:

1
scrapy startproject 项目名称

该命令成功执行后,应包含如下目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
doodlexu@MacBook tutorial % tree
.
├── scrapy.cfg
└── tutorial
├── __init__.py
├── items.py
├── middlewares.py
├── pipelines.py
├── settings.py
└── spiders
└── __init__.py

2 directories, 7 files

这些文件分别是:

  • scrapy.cfg: 项目的配置文件
  • tutorial/: 该项目的python模块。之后您将在此加入代码。
  • tutorial/items.py: 项目中的item文件.
  • tutorial/pipelines.py: 项目中的pipelines文件.
  • tutorial/settings.py: 项目的设置文件.
  • tutorial/spiders/: 放置spider代码的目录.

定义Item

Item是爬取到的数据的容器,他的语法很简单,和python字典(dict)类似,并且提供了额外保护机制来避免拼写错误导致的未定义字段错误。

类似在ORM中做的一样,您可以通过创建一个 scrapy.Item类, 并且定义类型为 scrapy.Field 的类属性来定义一个Item。其写法如下:

1
2
3
4
5
6
7
8
9
import scrapy

class douban_shortItem(scrapy.Item):
votes = scrapy.Field() # 有用投票
id = scrapy.Field() # 用户ID
rating = scrapy.Field() # 用户打分
date = scrapy.Field() # 短评日期
content = scrapy.Field() # 短评内容

编写爬虫

Spider是用户编写用于从单个网站(或者一些网站)爬取数据的类。

其包含了一个用于下载的初始URL,如何跟进网页中的链接以及如何分析页面中的内容, 提取生成 item 的方法。

为了创建一个Spider,您必须继承 scrapy.Spider 类, 且定义以下三个属性:

  • name: 用于区别Spider。 该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。
  • start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
  • parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。

以下为我们的Spider代码,它的目标是爬取电影(毒液2)的首页短评,并保存。代码需放在 tutorial/spiders 目录下的 douban_short.py 文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import scrapy

from mySpider.items import douban_shortItem


class DoubanShortSpider(scrapy.Spider):
name = 'douban_short'
allowed_domains = ['douban.com']

headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36'
}

cookies = {
'your_cookies' = 'your_values',
}

def start_requests(self):
url = 'https://movie.douban.com/subject/30382416/comments'
yield scrapy.Request(url, headers=self.headers, cookies=self.cookies)

def parse(self, response):
item = douban_shortItem()
shorts = response.xpath('//div[@id="comments"]/div')
for short in shorts:
try:
item['votes'] = short.xpath(
'.//div[2]/h3/span[1]/span/text()').extract()[0]
item['id'] = short.xpath(
'.//div[2]/h3/span[2]/a/text()').extract()[0]
item['rating'] = short.xpath(
'.//div[2]/h3/span[2]/span[2]/@class').re(u'\d')[0]
item['date'] = short.xpath(
'.//div[2]/h3/span[2]/span[3]/text()').extract()[0].strip()
item['content'] = short.xpath(
'.//div[2]/p/span/text()').extract()[0]
yield item
except:
pass

在爬取豆瓣的过程中,我们需要使用到cookies这项技术,它可以帮助服务器认识你是谁,给我们的小蜘蛛提供一层掩护,这样他就不会拒绝提供数据了。

另一个需要注意的点就是我们的headers,它的作用也和cookies类似,不过它不具备标识到个人,而是标识你用的是什么类型的浏览器和设备,以确保能正确解码。

这两项参数都可以在浏览器的开发者工具中找到,相信聪明的你一定可以的🤪

自动翻页

看到这,你肯定也发现了,到目前为止,这个小蜘蛛虽然干得很不错,顺利的拿到了数据,但还不够,我们需要所有数据。但是豆瓣为了保证用户体验,做了分页处理,这个时候要怎么办呢?

你已经是个成熟的🕷️了,你得学会自己翻页

回想一下,我们正常通过浏览器访问的时候,看下一页是通过点击次页按钮来实现的,那么我们的蜘蛛也可以这么做。我们可以通过xpath来定位到下一页按钮的目标的URL,并且只要它存在,我们就继续放🕷️:

1
2
3
4
next_url = response.xpath('//*[@id="paginator"]/a[@class="next"]/@href').extract()
if next_url:
next_url = 'https://movie.douban.com/subject/30382416/comments' + next_url[0]
yield scrapy.Request(next_url, headers=self.headers, cookies=self.cookies)

至此,我们已经可以遍历所有的评论了。

爬取

进入项目的根目录,执行下列命令启动spider:

1
scrapy crawl douban_short

命令执行后会有一大堆调试日志输出,别紧张,这是正常的。你可以在setting.py里随意调整日志输出级别:

1
2
3
4
5
import logging

...
LOG_LEVEL = logging.DEBUG # 日志输出级别
...

保存

执行上面命令会爬,但不会存,我们需要利用一个-O的参数来指定保存的文件名以及格式,比如像这样:

1
scrapy crawl douban_short -O shorts.csv

他会将保存到item里面的数据保存到shorts.cvs文件里,而且scrapy会自动辨别你的文件格式,自动的解析并保存。它支持的格式有:

  • json
  • jsonlines
  • jl
  • csv
  • xml
  • marshal
  • pickle