Scrapy初体验

安装

我是pip3 install Scrapy一梭子完事,但是看文档貌似还要搞搞xcode…

可以参考官方文档Scrapy安装指南

初始化项目

1
scrapy startproject douban_book

scrapy会自动初始化一个目录,里面有一些必须的文件,其结构如下:

1
2
3
4
5
6
7
8
9
10
11
.
├── README.md
├── __init__.py
├── __pycache__
├── items.py
├── middlewares.py
├── pipelines.py
├── settings.py
└── spiders
├── __init__.py
└── __pycache__

  • scrapy.cfg: 项目的配置文件
  • items.py: 项目的目标文件
  • pipelines.py: 项目的管道文件
  • settings.py: 项目的设置文件
  • spiders: 爬虫代码目录

构建项目

定义数据

首先我们需要定义我们想要抓取什么数据,编辑item.py,Item定义结构化数据字段,用来保存爬取到的数据,有点像Python中的dict,但是提供了一些额外的保护减少错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

class DoubanBookItem(scrapy.Item):

# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field() #书名
link = scrapy.Field() #链接
author = scrapy.Field() #作者
score = scrapy.Field() #评分
scoreNum = scrapy.Field() #评论人数
press = scrapy.Field() #出版社
isbn = scrapy.Field() #isbn
price = scrapy.Field() #价格
publishyear = scrapy.Field() #出版年
authordesc = scrapy.Field() #作者简介
bookdesc = scrapy.Field() #书简介
label = scrapy.Field() #标签
pagecount = scrapy.Field() #字数
imgurl = scrapy.Field() #图片链接

编写爬虫

爬数据

我们需要用scrapy.Spider类创建一个子类,并为其确定三个强制的属性。

  • name = “” :这个爬虫的识别名称,必须是唯一的,在不同的爬虫必须定义不同的名字。
  • allow_domains = [] 是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页,不存在的URL会被忽略
  • start_urls = () :爬取的URL元祖/列表。爬虫从这里开始抓取数据,并根据子url继续往下爬。
1
2
3
name = "douban_book"
allowed_domains = ["douban.com"] #搜索的域名范围,也就是爬虫的约束区域
start_urls = ['https://book.douban.com/subject/25794620/']

取数据

parse()方法解析数据,这里运用了XPATH,虽然以前用的BeautifulSoup4,不过都是解析啦 这个问题不大。
chrome浏览器提供检查->选中元素->copy->XPATH的快捷方式获取这个,我写的时候一边写一边测试的。

1
2
3
4
#举个栗子
title = response.xpath("//div[@id='wrapper']/h1/span/text()").extract()
link = response.url
imgurl = response.xpath("//div[@id='mainpic']/a[@class='nbg']/@href").extract_first()

存储数据

现在我们已经获取我们想要的数据了,下一步就是把他们存下来,可以存成csv文件,或者直接存到数据库里。这里选择保存到MySQL。

在pipelines.py里定义process_item()方法,在这里可以对数据做一定的处理,比如缺失值异常值之类的,然后存入数据库。

1
2
3
4
5
6
7
8
def process_item(self, item, spider):
rep = re.compile('\n| ')
title = item.get('title','N/A')
author_tmp = item.get('author','N/A')
#省略一部分
sql = "replace into book_info (title,author,score,press,isbn,price,publishyear,label,pagecount) values (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
self.cursor.execute(sql,(title,author,score,press,isbn,price,publishyear,label,pagecount))
self.conn.commit()

最终结果如下:

1
2
3
4
5
6
7
8
9
10
11
         id: 75
title: 沉默的大多数
author: 王小波
score: 9.1
scorenum: 0
press: 中国青年出版社
isbn: 9787500627098
price: 27.0000
publishyear: 1997-10
label: 王小波,杂文,沉默的大多数,思想,随笔,中国文学,文学,中国
pagecount: 555

ToDo

  • 页面解析并不是很好,经常缺数据
  • 加入redis
  • 会被封IP,需要加ip池