概述
在前面两篇(爬虫学习之基于Scrapy的网络爬虫和爬虫学习之简单的网络爬虫)文章中我们通过两个实际的案例,采用不同的方式进行了内容提取。我们对网络爬虫有了一个比较初级的认识,只要发起请求获取响应的网页内容,然后对内容进行格式化存储。很多时候我们抓取到的内容可能会发生重复,也有可能是需要计算或者组织过的全新的内容甚至是需要登录后才能访问的内容, 那么这一篇我们来学习一下Scrapy的Item部分以及了解如何使用Scrapy来进行自动登录。
起步
首先我们使用Scrapy的命令行创建一个新的项目
1 |
scrapy startproject douban |
运行后,我们就有了下面这样的目录结构
1 2 3 4 5 6 7 8 9 |
+ douban # 根目录 |- douban # Python的项目目录 |- spiders # 爬虫Spider部分,用于提取网页内容 |- __init__.py |- __init__.py |- items.py # 爬虫item, 用于定义数据结构 |- pipelines.py # 爬虫pipeline,用于处理提取的结构,比如清洗数据、去重等 |- settings.py # Scrapy框架参数项目参数设置 |- scrapy.cfg # 爬虫部署相关设置 |
Scrapy为我们生成了已经组织好的目录结构,上面的注释部分解释了每个文件及目录的作用。
建立目标
本篇我们来建立两个目标,这两个目标都是基于豆瓣网:
- 目标一:抓取豆瓣TOP250的图书信息并保存成csv文件
- 目标二:抓取我的第一页豆邮标题(需要登录),并保存成csv文件
分析目标一
目标一是豆瓣的TOP250图书信息,首先我们进入到TOP250的列表(https://book.douban.com/top250) ,我用图示圈出我们这次要爬取的内容,具体请看图示:
从图上的框线中我们主要圈出了书名、价格、出版年份、出版社、评分,其中出版年份,出版社以及价格是在一行中,这个我们需要进一步处理。
分页的处理:总记录是250条,每页是25条图书信息,共分了10页。
实现目标一
需要用到的概念:
- Item
- Item Pipeline
首先建立Scrapy的Item, Scrapy的Item就是我们需要存储的数据结构,先修改items, 然后在spiders目录中新建一个名为bookspider.py的Python文件,由于我们需要在一堆字符串中提取出出版社和价格等信息所以我们这里需要对抓取的内容进一步处理, 在这之前还需要修改settings.py文件:
- 加入faker的模拟USER_AGENT数据防止被豆瓣屏蔽,
- 也可以设置DEFAULT_REQUEST_HEADERS参数。
- 修改ITEM_PIPELINES
代码如下所示:
items.py
1 2 3 4 5 6 7 8 9 10 11 |
# -*- coding: utf-8 -*- '''by sudo rm -rf http://imchenkun.com''' import scrapy class DoubanBookItem(scrapy.Item): name = scrapy.Field() # 书名 price = scrapy.Field() # 价格 edition_year = scrapy.Field() # 出版年份 publisher = scrapy.Field() # 出版社 ratings = scrapy.Field() # 评分 |
bookspider.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 |
# -*- coding:utf-8 -*- '''by sudo rm -rf http://imchenkun.com''' import scrapy from douban.items import DoubanBookItem class BookSpider(scrapy.Spider): name = 'douban-book' allowed_domains = ['douban.com'] start_urls = [ 'https://book.douban.com/top250' ] def parse(self, response): # 请求第一页 yield scrapy.Request(response.url, callback=self.parse_next) # 请求其它页 for page in response.xpath('//div[@class="paginator"]/a'): link = page.xpath('@href').extract()[0] yield scrapy.Request(link, callback=self.parse_next) def parse_next(self, response): for item in response.xpath('//tr[@class="item"]'): book = DoubanBookItem() book['name'] = item.xpath('td[2]/div[1]/a/@title').extract()[0] book['price'] = item.xpath('td[2]/p/text()').extract()[0] book['ratings'] = item.xpath('td[2]/div[2]/span[2]/text()').extract()[0] yield book |
pipelines.py
1 2 3 4 5 6 7 8 9 10 11 12 |
# -*- coding: utf-8 -*- '''by sudo rm -rf http://imchenkun.com''' class DoubanBookPipeline(object): def process_item(self, item, spider): info = item['price'].split(' / ') # [法] 圣埃克苏佩里 / 马振聘 / 人民文学出版社 / 2003-8 / 22.00元 item['name'] = item['name'] item['price'] = info[-1] item['edition_year'] = info[-2] item['publisher'] = info[-3] return item |
最后我们到douban的根目录中执行以下命令来运行爬虫来执行并导出数据到csv文件
1 |
scrapy crawl douban-book -o douban_book_top250.csv |
csv文件截图如下:
分析目标二
目标二是建立在理解了目标一的基础上进行的,因为豆瓣登录次数过多会有验证码出现,这里提供一种手工填写验证码的方式,暂时不讨论如何去识别验证码,目标二的核心概念是如何提交POST表单和登录成功后带Cookie的请求。首先我们可以看到页面结构如下图所示:
实现目标二
定义Item
1 2 3 4 5 6 7 8 9 |
# -*- coding: utf-8 -*-import scrapy '''by sudo rm -rf http://imchenkun.com''' class DoubanMailItem(scrapy.Item): sender_time = scrapy.Field() # 发送时间 sender_from = scrapy.Field() # 发送人 url = scrapy.Field() # 豆邮详细地址 title = scrapy.Field() # 豆邮标题 |
定义doumailspider
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# -*- coding:utf-8 -*- '''by sudo rm -rf http://imchenkun.com''' import scrapy from faker import Factory from douban.items import DoubanMailItem import urlparse f = Factory.create() class MailSpider(scrapy.Spider): name = 'douban-mail' allowed_domains = ['accounts.douban.com', 'douban.com'] start_urls |