在前面两篇(爬虫学习之基于Scrapy的网络爬虫和爬虫学习之简单的网络爬虫)文章中咱们经过两个实际的案例,采用不一样的方式进行了内容提取。咱们对网络爬虫有了一个比较初级的认识,只要发起请求获取响应的网页内容,而后对内容进行格式化存储。不少时候咱们抓取到的内容可能会发生重复,也有多是须要计算或者组织过的全新的内容甚至是须要登陆后才能访问的内容, 那么这一篇咱们来学习一下Scrapy的Item部分以及了解如何使用Scrapy来进行自动登陆。html
首先咱们使用Scrapy的命令行建立一个新的项目git
scrapy startproject douban
运行后,咱们就有了下面这样的目录结构github
+ douban # 根目录 |- douban # Python的项目目录 |- spiders # 爬虫Spider部分,用于提取网页内容 |- __init__.py |- __init__.py |- items.py # 爬虫item, 用于定义数据结构 |- pipelines.py # 爬虫pipeline,用于处理提取的结构,好比清洗数据、去重等 |- settings.py # Scrapy框架参数项目参数设置 |- scrapy.cfg # 爬虫部署相关设置
Scrapy为咱们生成了已经组织好的目录结构,上面的注释部分解释了每一个文件及目录的做用。浏览器
本篇咱们来创建两个目标,这两个目标都是基于豆瓣网:服务器
目标一:抓取豆瓣TOP250的图书信息并保存成csv文件cookie
目标二:抓取个人第一页豆邮标题(须要登陆),并保存成csv文件网络
目标一是豆瓣的TOP250图书信息,首先咱们进入到TOP250的列表(https://book.douban.com/top250) ,我用图示圈出咱们此次要爬取的内容,具体请看图示:session
从图上的框线中咱们主要圈出了书名、价格、出版年份、出版社、评分,其中出版年份,出版社以及价格是在一行中,这个咱们须要进一步处理。数据结构
分页的处理:总记录是250条,每页是25条图书信息,共分了10页。app
须要用到的概念:
Item
Item Pipeline
首先创建Scrapy的Item, Scrapy的Item就是咱们须要存储的数据结构,先修改items, 而后在spiders目录中新建一个名为bookspider.py的Python文件,因为咱们须要在一堆字符串中提取出出版社和价格等信息因此咱们这里须要对抓取的内容进一步处理, 在这以前还须要修改settings.py文件:
加入faker的模拟USER_AGENT数据防止被豆瓣屏蔽,
也能够设置DEFAULT_REQUEST_HEADERS参数。
修改ITEM_PIPELINES
代码以下所示:
items.py
# -*- 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
# -*- 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
# -*- 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文件
scrapy crawl douban-book -o douban_book_top250.csv
csv文件截图以下:
目标二是创建在理解了目标一的基础上进行的,由于豆瓣登陆次数过多会有验证码出现,这里提供一种手工填写验证码的方式,暂时不讨论如何去识别验证码,目标二的核心概念是如何提交POST表单和登陆成功后带Cookie的请求。首先咱们能够看到页面结构以下图所示:
定义Item
# -*- 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
# -*- 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 = [ 'https://www.douban.com/' ] headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 'Connection': 'keep-alive', 'Host': 'accounts.douban.com', 'User-Agent': f.user_agent() } formdata = { 'form_email': '您的帐号', 'form_password': '您的密码', # 'captcha-solution': '', # 'captcha-id': '', 'login': '登陆', 'redir': 'https://www.douban.com/', 'source': 'None' } def start_requests(self): return [scrapy.Request(url='https://www.douban.com/accounts/login', headers=self.headers, meta={'cookiejar': 1}, callback=self.parse_login)] def parse_login(self, response): # 若是有验证码要人为处理 if 'captcha_image' in response.body: print 'Copy the link:' link = response.xpath('//img[@class="captcha_image"]/@src').extract()[0] print link captcha_solution = raw_input('captcha-solution:') captcha_id = urlparse.parse_qs(urlparse.urlparse(link).query, True)['id'] self.formdata['captcha-solution'] = captcha_solution self.formdata['captcha-id'] = captcha_id return [scrapy.FormRequest.from_response(response, formdata=self.formdata, headers=self.headers, meta={'cookiejar': response.meta['cookiejar']}, callback=self.after_login )] def after_login(self, response): print response.status self.headers['Host'] = "www.douban.com" return scrapy.Request(url='https://www.douban.com/doumail/', meta={'cookiejar': response.meta['cookiejar']}, headers=self.headers, callback=self.parse_mail) def parse_mail(self, response): print response.status for item in response.xpath('//div[@class="doumail-list"]/ul/li'): mail = DoubanMailItem() mail['sender_time'] = item.xpath('div[2]/div/span[1]/text()').extract()[0] mail['sender_from'] = item.xpath('div[2]/div/span[2]/text()').extract()[0] mail['url'] = item.xpath('div[2]/p/a/@href').extract()[0] mail['title'] = item.xpath('div[2]/p/a/text()').extract()[0] print mail yield mail
这里须要注意的有三个地方:
第一个是meta中的cookiejar
Scrapy 经过使用 cookiejar Request meta key来支持单spider追踪多cookie session。默认状况下其使用一个cookie jar(session),不过您能够传递一个标示符来使用多个。
start_requests 咱们这里重写了爬虫爬取得第一个页面,这里一开始就进去到登陆页面
当执行爬虫的时候,咱们须要把打印出来的验证码地址粘贴到浏览器中,手动输入到控制上完成验证。
同目标一同样须要设置settings中的相关参数,惟一不一样的是ITEM_PIPELINES。
最后咱们使用如下命令来启动爬虫
scrapy crawl douban-mail -o douban_mail_page1.csv
csv文件截图以下:
Github地址:https://github.com/imchenkun/ick-spider/tree/master/douban
本篇咱们学习了若是定义Item以及如何对Item进行进一步处理(Item Pipeline), 还经过登陆豆瓣的案例来了解了若是使用Scrapy进行表单提交和Cookie追踪,也了解了对于有验证码的状况该如何处理,固然咱们这里暂时还不讨论如何识别验证码。关于Scrapy的更高级的一些用法和特性能够进一步阅读Scrapy官网的文档。
特别申明:本文所提到的豆瓣网只是拿来进行爬虫的技术交流学习,读者涉及到的全部侵权问题都与本人无关,也但愿你们在学习实战的过程当中不要大量的爬取内容对服务器形成负担
本文首发在sudo rm -rf 采用署名(BY)-非商业性使用(NC)-禁止演绎(ND) 转载请注明原做者
--EOF--