零、说明

  这个例子爬取了豆瓣top250电影,并把这些电影的某些属性保存到mysql中,具体的url是这个:https://movie.douban.com/top250。

一、环境

  • python3.4
  • mysql
  • python安装好scrapy

二、工作目录

Scrapy是Python开发的一个快速,高层次的屏幕抓取和Web抓取框架,用于抓取Web站点并从页面中提取结构化的数据。

下图展示了Scrapy的大致架构,其中包含了主要组件和系统的数据处理流程(绿色箭头表示)。下面会对组件和流程进行了一个简单的解释。

组件

1.Scrapy Engine(Scrapy引擎)

Scrapy引擎是用来控制整个系统的数据处理流程,并进行事务处理的触发。更多的详细内容可以看下面的数据处理流程。

2.Scheduler(调度程序)

调度程序从Scrapy引擎接受请求并排序列入队列,并在Scrapy引擎发出请求后返还给它们。

3.Downloader(下载器)

下载器的主要职责是抓取网页并将网页内容返还给蜘蛛(Spiders)。

4.Spiders(蜘蛛)

蜘蛛是有Scrapy用户自己定义用来解析网页并抓取制定URL返回的内容的类,每个蜘蛛都能处理一个域名或一组域名。换句话说就是用来定义特定网站的抓取和解析规则。

5.Item Pipeline(项目管道)

项目管道的主要责任是负责处理有蜘蛛从网页中抽取的项目,它的主要任务是清晰、验证和存储数据。当页面被蜘蛛解析后,将被发送到项目管道,并经过几个特定的次序处理数据。每个项目管道的组件都是有一个简单的方法组成的Python类。它们获取了项目并执行它们的方法,同时还需要确定的是是否需要在项目管道中继续执行下一步或是直接丢弃掉不处理。

项目管道通常执行的过程有:

清洗HTML数据 验证解析到的数据(检查项目是否包含必要的字段) 检查是否是重复数据(如果重复就删除) 将解析到的数据存储到数据库中

6.Middlewares(中间件)

中间件是介于Scrapy引擎和其他组件之间的一个钩子框架,主要是为了提供一个自定义的代码来拓展Scrapy的功能。

数据处理流程

Scrapy的整个数据处理流程有Scrapy引擎进行控制,其主要的运行方式为:

  1. 引擎打开一个域名,时蜘蛛处理这个域名,并让蜘蛛获取第一个爬取的URL。
  2. 引擎从蜘蛛那获取第一个需要爬取的URL,然后作为请求在调度中进行调度。
  3. 引擎从调度那获取接下来进行爬取的页面。
  4. 调度将下一个爬取的URL返回给引擎,引擎将它们通过下载中间件发送到下载器。
  5. 当网页被下载器下载完成以后,响应内容通过下载中间件被发送到引擎。
  6. 引擎收到下载器的响应并将它通过蜘蛛中间件发送到蜘蛛进行处理。
  7. 蜘蛛处理响应并返回爬取到的项目,然后给引擎发送新的请求。
  8. 引擎将抓取到的项目项目管道,并向调度发送请求。
  9. 系统重复第二部后面的操作,直到调度中没有请求,然后断开引擎与域之间的联系。

实例展示

在开始之前,我假定你已经安装了Scrapy。如果你还没有安装成功,具体的安装过程请参考官方文档,Win7 64位的请参考此链接。(不过说实话,安装Scrapy真心蛋疼啊,因为它需要安装很多其他依赖的组件,出现各种异常问题在StackOverflow找解决办法吧。)

新建工程

这次我们来用爬虫获取豆瓣电影Top 250的电影信息吧。开始之前,我们新建一个Scrapy工程。因为我用的Win7,所以在CMD中进入一个我希望保存代码的目录,然后执行:

D:\WEB\Python>scrapy startproject doubanmoive

这个命令会在当前目录下创建一个新的目录doubanmoive,目录结构如下:

D:\WEB\Python\doubanmoive>tree /f
Folder PATH listing for volume Data
Volume serial number is 00000200 34EC:9CB9
D:.
│  scrapy.cfg
│
└─doubanmoive│  items.py│  pipelines.py│  settings.py│  __init__.py│└─spiders__init__.py

这些文件主要为:

  • doubanmoive/items.py:定义需要获取的内容字段,类似于实体类。
  • doubanmoive/pipelines.py:项目管道文件,用来处理Spider抓取的数据。
  • doubanmoive/settings.py:项目配置文件
  • doubanmoive/spiders:放置spider的目录

定义项目(Item)

Item是用来装载抓取数据的容器,和Java里的实体类(Entity)比较像,打开doubanmoive/items.py可以看到默认创建了以下代码。

from scrapy.item import Item, Fieldclass DoubanmoiveItem(Item):pass

我们只需要在Doubanmoive类中增加需要抓取的字段即可,如name=Field(),最后根据我们的需求完成代码如下。

from scrapy.item import Item, Fieldclass DoubanmoiveItem(Item):name=Field()#电影名year=Field()#上映年份score=Field()#豆瓣分数director=Field()#导演classification=Field()#分类actor=Field()#演员

编写爬虫(Spider)

Spider是整个项目中最核心的类,在这个类里我们会定义抓取对象(域名、URL)以及抓取规则。Scrapy官方文档中的教程是基于BaseSpider的,但BaseSpider只能爬取给定的URL列表,无法根据一个初始的URL向外拓展。不过除了BaseSpider,还有很多可以直接继承Spider的类,比如scrapy.contrib.spiders.CrawlSpider

doubanmoive/spiders目录下新建moive_spider.py文件,并填写代码。

# -*- coding: utf-8 -*-
from scrapy.selector import Selector
from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.linkextractors import LinkExtractor
from doubanmoive.items import DoubanmoiveItemclass MoiveSpider(CrawlSpider):    name="doubanmoive"    allowed_domains=["movie.douban.com"]    start_urls=["http://movie.douban.com/top250"]    rules=[        Rule(LinkExtractor(allow=(r'http://movie.douban.com/top250\?start=\d+.*'))),        Rule(LinkExtractor(allow=(r'http://movie.douban.com/subject/\d+')),callback="parse_item"),          ]    def parse_item(self,response):        sel=Selector(response)        item=DoubanmoiveItem()        item['name']=sel.xpath('//*[@id="content"]/h1/span[1]/text()').extract()        item['year']=sel.xpath('//*[@id="content"]/h1/span[2]/text()').re(r'\((\d+)\)')        item['score']=sel.xpath('//*[@id="interest_sectl"]/div/p[1]/strong/text()').extract()        item['director']=sel.xpath('//*[@id="info"]/span[1]/a/text()').extract()        item['classification']= sel.xpath('//span[@property="v:genre"]/text()').extract()        item['actor']= sel.xpath('//*[@id="info"]/span[3]/a[1]/text()').extract()        return item

代码说明:MoiveSpider继承Scrapy中的CrawlSpidername , allow_domains , start_url看名字就知道什么含义,其中rules稍微复杂一些,定义了URL的抓取规则,符合allow正则表达式的链接都会加入到Scheduler(调度程序)。通过分析豆瓣电影Top250的分页URLhttp://movie.douban.com/top250?start=25&filter=&type=可以得到以下规则:

Rule(SgmlLinkExtractor(allow=(r'http://movie.douban.com/top250\?start=\d+.*'))),

而我们真正要抓取的页面是每一个电影的详细介绍,如《肖申克的救赎》的链接为http://movie.douban.com/subject/1292052/,那只有subject后面的数字是变化的,根据正则表达式得到如下代码。我们需要抓取这种类型链接中的内容,于是加入callback属性,将Response交给parse_item函数来处理。

Rule(SgmlLinkExtractor(allow=(r'http://movie.douban.com/subject/\d+')),callback="parse_item"),      

parse_item函数中的处理逻辑非常简单,获取符合条件链接的代码,然后根据一定的规则抓取内容赋给item并返回Item Pipeline。获取大部分标签的内容不需要编写复杂的正则表达式,我们可以使用XPath。 XPath 是一门在 XML 文档中查找信息的语言,但它也可以用在HTML中。下表列出了常用表达式。

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。

//*[@id="content"]/h1/span[1]/text()获取的结果是在id为content的任意元素下h1元素下的span列表中第一个元素的文本内容。我们可以通过Chrome开发者工具(F12)来获取某内容的XPath表达式,具体操作为在需要抓取的内容上点击审查元素,下方就会出现开发者工具,并定位到该元素,在内容上点击右键,选择复制XPath。

[+]查看原图

存储数据

爬虫获取到数据以后我们需要将其存储到数据库中,之前我们提到该操作需要靠项目管道(pipeline)来处理,其通常执行的操作为:

  • 清洗HTML数据
  • 验证解析到的数据(检查项目是否包含必要的字段)
  • 检查是否是重复数据(如果重复就删除)
  • 将解析到的数据存储到数据库中

由于我们获取的数据格式多种多样,有一些存储在关系型数据库中并不方便,所以我在写完MySQL版本的Pipeline之后又写了一个MongoDB的。

MySQL代码:

# -*- coding: utf-8 -*-
from scrapy import log
from twisted.enterprise import adbapi
from scrapy.http import Requestimport MySQLdb
import MySQLdb.cursorsclass DoubanmoivePipeline(object):def __init__(self):self.dbpool = adbapi.ConnectionPool('MySQLdb',db = 'python',user = 'root',passwd = 'root',cursorclass = MySQLdb.cursors.DictCursor,charset = 'utf8',use_unicode = False)def process_item(self, item, spider):query = self.dbpool.runInteraction(self._conditional_insert, item)query.addErrback(self.handle_error)return itemdef _conditional_insert(self,tx,item):tx.execute("select * from doubanmoive where m_name= %s",(item['name'][0],))result=tx.fetchone()log.msg(result,level=log.DEBUG)print resultif result:log.msg("Item already stored in db:%s" % item,level=log.DEBUG)else:classification=actor=''lenClassification=len(item['classification'])lenActor=len(item['actor'])for n in xrange(lenClassification):classification+=item['classification'][n]if n<lenClassification-1:classification+='/'for n in xrange(lenActor):actor+=item['actor'][n]if n<lenActor-1:actor+='/'tx.execute(\"insert into doubanmoive (m_name,m_year,m_score,m_director,m_classification,m_actor) values (%s,%s,%s,%s,%s,%s)",\(item['name'][0],item['year'][0],item['score'][0],item['director'][0],classification,actor))log.msg("Item stored in db: %s" % item, level=log.DEBUG)def handle_error(self, e):log.err(e)

MongoDB代码:

# -*- coding: utf-8 -*-
import pymongofrom scrapy.exceptions import DropItem
from scrapy.conf import settings
from scrapy import logclass MongoDBPipeline(object):#Connect to the MongoDB databasedef __init__(self):connection = pymongo.Connection(settings['MONGODB_SERVER'], settings['MONGODB_PORT'])db = connection[settings['MONGODB_DB']]self.collection = db[settings['MONGODB_COLLECTION']]def process_item(self, item, spider):#Remove invalid datavalid = Truefor data in item:if not data:valid = Falseraise DropItem("Missing %s of blogpost from %s" %(data, item['url']))if valid:#Insert data into databasenew_moive=[{"name":item['name'][0],"year":item['year'][0],"score":item['score'][0],"director":item['director'],"classification":item['classification'],"actor":item['actor']}]self.collection.insert(new_moive)log.msg("Item wrote to MongoDB database %s/%s" %(settings['MONGODB_DB'], settings['MONGODB_COLLECTION']),level=log.DEBUG, spider=spider) return item

可以看到其基本的处理流程是一样,但是MySQL不太方便的一点就是需要将数组类型的数据通过分隔符转换。而MongoDB支持存入List、Dict等多种类型的数据。

配置文件

在运行爬虫之前还需要将在settings.py中增加一些配置信息。

如何防止蜘蛛被网站Ban掉

首先可以尝试添加登陆用户的cookie去抓取网页,即使你抓取的是公开网页,添加cookie有可能会防止蜘蛛在应用程序层被禁。这个我没有实际验证过,但肯定没有坏处。

其次,即使你是授权用户,如果你的访问过于频繁,你的IP会可能被ban,所以一般你需要让蜘蛛在访问网址中间休息1~2秒。

还有就是配置User Agent,尽量轮换使用不同的UserAgent去抓取网页

在Scrapy项目的settings.py钟,添加如下设置:

BOT_NAME = 'doubanmoive'
SPIDER_MODULES = ['doubanmoive.spiders']
NEWSPIDER_MODULE = 'doubanmoive.spiders'
ITEM_PIPELINES={'doubanmoive.mongo_pipelines.MongoDBPipeline':300,'doubanmoive.pipelines.DoubanmoivePipeline':400,
}
LOG_LEVEL='DEBUG'
DOWNLOAD_DELAY = 2
RANDOMIZE_DOWNLOAD_DELAY = True
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5'
COOKIES_ENABLED = TrueMONGODB_SERVER = 'localhost'
MONGODB_PORT = 27017
MONGODB_DB = 'python'
MONGODB_COLLECTION = 'test'

ITEM_PIPELINES中定义了MySQL和MongoDB两个Pipeline文件,后面的数字代表执行的优先级顺序,范围为0~1000。而中间的DOWNLOAD_DELAY等信息是为了防止爬虫被豆瓣Ban掉,增加了一些随机延迟,浏览器代理等。最后的就是MongoDB的配置信息,MySQL也可以参考这种方式来写。

至此为止,抓取豆瓣电影的爬虫就已经完成了。在命令行中执行Scrapy crawl doubanmoive让蜘蛛开始爬行吧!

Scrapy抓取豆瓣电影相关推荐

  1. python,抓取豆瓣电影,再也不用担心没有看不了的电影了

    1. 豆瓣抓站流程 分析url特征(菜鸟阶段) 对需要抓取的数据设计正则表达式 处理HTML中一些特征字符,换行符等 注意异常的处理和字符编码的处理 2. 实现的功能 简单的实现了抓取豆瓣电影Top1 ...

  2. python2.7抓取豆瓣电影top250

    利用python2.7抓取豆瓣电影top250 1.任务说明 抓取top100电影名称 依次打印输出 2.网页解析 要进行网络爬虫,利用工具(如浏览器)查看网页HTML文件的相关内容是很有必要,我使用 ...

  3. 从抓取豆瓣电影聊高性能爬虫思路(纯干货)

    从抓取豆瓣电影聊高性能爬虫思路 本篇文章将以抓取豆瓣电影信息为例来一步步介绍开发一个高性能爬虫的常见思路. 寻找数据地址 爬虫的第一步,首先我们要找到获取数据的地址.可以先到豆瓣电影 首页 去看看. ...

  4. 从抓取豆瓣电影聊高性能爬虫思路

    本篇文章将以抓取豆瓣电影信息为例来一步步介绍开发一个高性能爬虫的常见思路. 寻找数据地址 爬虫的第一步,首先我们要找到获取数据的地址.可以先到豆瓣电影 首页 去看看. 顶部导航为提供了很多种类型的入口 ...

  5. 编写Python爬虫抓取豆瓣电影TOP100及用户头像的方法

    这篇文章主要介绍了编写Python爬虫抓取豆瓣电影TOP100及用户头像的方法,用到了Python的urllib和urllib2模块,需要的朋友可以参考下 抓取豆瓣电影TOP100 一.分析豆瓣top ...

  6. 不会 Python 没关系,手把手教你用 web scraper 抓取豆瓣电影 top 250 和 b 站排行榜

    苏生不惑第190 篇原创文章,将本公众号设为 星标 ,第一时间看最新文章. 关于Python之前分享过很多文章了: Python 抓取知乎电影话题下万千网友推荐的电影,这个国庆节不愁没电影看了 王菲k ...

  7. python爬取豆瓣电影top250_【Python3爬虫教程】Scrapy爬取豆瓣电影TOP250

    今天要实现的就是使用是scrapy爬取豆瓣电影TOP250榜单上的电影信息. 步骤如下: 一.爬取单页信息 首先是建立一个scrapy项目,在文件夹中按住shift然后点击鼠标右键,选择在此处打开命令 ...

  8. Python3 抓取豆瓣电影Top250

    利用 requests 抓取豆瓣电影 Top 250: import re import requestsdef main(url):global numheaders = {"User-A ...

  9. 不会写Python代码如何抓取豆瓣电影 Top 250

    说到爬虫,大多数人会想到用Python来做,毕竟简单好用,比如想抓取豆瓣电影top250 的所有电影数据. 简单的代码如下: import requests from bs4 import Beaut ...

最新文章

  1. Java日志体系总结
  2. 把BERT拉下神坛!ACL论文只靠一个“Not”,就把AI阅读理解骤降到盲猜水平
  3. window 桌面开发_C#桌面开发的未来WebWindow
  4. 【转】简述configure、pkg-config、pkg_config_path三者的关系
  5. 红黑树(二)之 C语言的实现
  6. 5.Spring Cloud Alibaba教程:Nacos整合Feign
  7. QuerWrapper常用方法
  8. ZigBee TI ZStack CC2530 8.4 如何用高版本IAR打开低版本协议栈
  9. 微软亚研院 | 智能信息检索综述
  10. 驱动lx4f120h,头文件配置,没有完全吃透,望指点
  11. dart安装:sdk下载地址( 2.4.0)
  12. 软件开发中的需求种类
  13. 第三方SDK:SMSSDK
  14. Oracle 根据dbf文件的数据恢复
  15. PS画虚线的几种方法
  16. H3C MSR 2600-10 Winet 交换机consol口设置
  17. float a=1.0f 这里的1.0f中的 f 代表什么?有什么意思?
  18. 台式机安装纯ubuntu系统的操作步骤
  19. 数据分析之 —— 常用的统计学指标
  20. 阿里员工内部常用免费工具包

热门文章

  1. HIS各模块业务操作流程明白纸
  2. RFID仓库管理系统之售后产品的管理-新导智能
  3. Stata 转 Excel —— export excel 命令详解
  4. 中级篇——Linux下通过进程名、ID、端口号查看进程信息
  5. 修改 TeamViewer ID 的方法
  6. Are You Talking to Me? Reasoned Visual Dialog Generation through Adversarial Learning
  7. NV040C语音单片机芯片,节省MCU开发成本,在电取暖桌上的应用!
  8. 码云简易上传的详细说明
  9. xss challenges闯关详细(6-10)
  10. sqlplus的简单使用和常用命令