crawlspider cookie如何获取最初的start

Spiders & Scrapy 1.0.5 文档&&28960 阅读
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引擎进行控制,其主要的运行方式为:
引擎打开一个域名,时蜘蛛处理这个域名,并让蜘蛛获取第一个爬取的URL。
引擎从蜘蛛那获取第一个需要爬取的URL,然后作为请求在调度中进行调度。
引擎从调度那获取接下来进行爬取的页面。
调度将下一个爬取的URL返回给引擎,引擎将它们通过下载中间件发送到下载器。
当网页被下载器下载完成以后,响应内容通过下载中间件被发送到引擎。
引擎收到下载器的响应并将它通过蜘蛛中间件发送到蜘蛛进行处理。
蜘蛛处理响应并返回爬取到的项目,然后给引擎发送新的请求。
引擎将抓取到的项目项目管道,并向调度发送请求。
系统重复第二部后面的操作,直到调度中没有请求,然后断开引擎与域之间的联系。
在开始之前,我假定你已经安装了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 EC:9CB9
scrapy.cfg
└─doubanmoive
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, Field
class DoubanmoiveItem(Item):
我们只需要在Doubanmoive类中增加需要抓取的字段即可,如name=Field(),最后根据我们的需求完成代码如下。
from scrapy.item import Item, Field
class 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.contrib.linkextractors.sgml import SgmlLinkExtractor
from doubanmoive.items import DoubanmoiveItem
class MoiveSpider(CrawlSpider):
name=&doubanmoive&
allowed_domains=[&&]
start_urls=[&/top250&]
Rule(SgmlLinkExtractor(allow=(r'/top250\?start=\d+.*'))),
Rule(SgmlLinkExtractor(allow=(r'/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中的CrawlSpider,name , allow_domains , start_url看名字就知道什么含义,其中rules稍微复杂一些,定义了URL的抓取规则,符合allow正则表达式的链接都会加入到Scheduler(调度程序)。通过分析豆瓣电影Top250的分页URL/top250?start=25&filter=&type=可以得到以下规则:
Rule(SgmlLinkExtractor(allow=(r'/top250\?start=\d+.*'))),
而我们真正要抓取的页面是每一个电影的详细介绍,如《肖申克的救赎》的链接为/subject/1292052/,那只有subject后面的数字是变化的,根据正则表达式得到如下代码。我们需要抓取这种类型链接中的内容,于是加入callback属性,将Response交给parse_item函数来处理。
Rule(SgmlLinkExtractor(allow=(r'/subject/\d+')),callback=&parse_item&),
在parse_item函数中的处理逻辑非常简单,获取符合条件链接的代码,然后根据一定的规则抓取内容赋给item并返回Item Pipeline。获取大部分标签的内容不需要编写复杂的正则表达式,我们可以使用XPath。
XPath 是一门在 XML 文档中查找信息的语言,但它也可以用在HTML中。下表列出了常用表达式。
选取此节点的所有子节点。
从根节点选取。
从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
选取当前节点。
选取当前节点的父节点。
选取属性。
如//*[@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 Request
import MySQLdb
import MySQLdb.cursors
class 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 item
def _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 result
if result:
log.msg(&Item already stored in db:%s& % item,level=log.DEBUG)
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 pymongo
from scrapy.exceptions import DropItem
from scrapy.conf import settings
from scrapy import log
class MongoDBPipeline(object):
#Connect to the MongoDB database
def __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 data
valid = True
for data in item:
if not data:
valid = False
raise DropItem(&Missing %s of blogpost from %s& %(data, item['url']))
#Insert data into database
new_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中增加一些配置信息。
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 (M Intel Mac OS X 10_8_3) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5'
COOKIES_ENABLED = True
MONGODB_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让蜘蛛开始爬行吧!爬虫(21)
自动多网页爬取,这里引出CrawlSpider类,使用更简单方式实现自动爬取。
1.CrawlSpider
(1)概念与作用:
它是Spider的派生类,首先在说下Spider,它是所有爬虫的基类,对于它的设计原则是只爬取start_url列表中的网页,而从爬取的网页中获取link并继续爬取的工作CrawlSpider类更适合。
(2)使用:
它与Spider类的最大不同是多了一个rules参数,其作用是定义提取动作。在rules中包含一个或多个Rule对象,Rule类与CrawlSpider类都位于scrapy.contrib.spiders模块中。
[python]&&
& & & & & & & & & & &其中:
link_extractor为LinkExtractor,用于定义需要提取的链接。
callback参数:当link_extractor获取到链接时参数所指定的值作为回调函数。
& & & & & &
& & & & & callback参数使用注意:
当编写爬虫规则时,请避免使用parse作为回调函数。于使用parse方法来实现其逻辑,如果您覆盖了parse方法,crawlspider将会运行失败。
follow:指定了根据该规则从response提取的链接是否需要跟进。当callback为None,默认值为true。
process_links:主要用来过滤由link_extractor获取到的链接。
process_request:主要用来过滤在rule中提取到的request。
2.LinkExtractor
(1)概念:
顾名思义,链接提取器。
(2) 作用:
response对象中获取链接,并且该链接会被接下来爬取。
(3) 使用:
通过SmglLinkExtractor提取希望获取的链接。
[python]&&
主要参数:
allow:满足括号中“正则表达式”的值会被提取,如果为空,则全部匹配。
deny:与这个正则表达式(或正则表达式列表)不匹配的URL一定不提取。
allow_domains:会被提取的链接的domains。
deny_domains:一定不会被提取链接的domains。
restrict_xpaths:使用xpath表达式,和allow共同作用过滤链接。
shell中验证
开始编写代码之前,使用scrapyshell查看使用SmglLinkExtractor在网页中获取到的链接:
[python]&&
继续import相关模块:
[python]&&
现在使用SgmlLinkExtractor查看在当前网页中获得的链接:
[python]&&
其中item为包含Link()对象的列表,现在显示其中的text元素(就是获取到的文章链接对应的文章标题):
[python]&&
部分结果截图:
对照网页可以得到此时获取的是当前网页中所有满足allow条件的链接,不仅包含“下一篇”的链接,还有网页侧边栏“阅读排行“、”评论排行“中的文章链接。为了只获得”下一篇“文章链接,这就要进行所有链接的筛选,引入参数restrict_xpaths,继续:
[python]&&
这是在如上查看结果,便提取出了“下一篇”文章链接。
注意:在shell中并不对提取到的link进行跟进。
在这里不得不提的就是scrapy shell是对调试、验证很有用的交互工具。应该掌握。
在shell中进行了验证后进入写代码阶段。
(1)items.py和pipelines.py以及settings.py与之前教程类似,不详细描述。
(2)爬虫编写。
[python]&&
[python]&&
得到的效果如教程(五)一致。
其中指出和教程(五)所编写爬虫方法的差异:
首先,基类CrawlSpider提供了更完善的自动多网页爬取机制,只需要我们配置的就是rules,通过Rule对象实现链接的提取与跟进,恩,对,没了。。。就这样。详细的注释也都在程序中。
进行到这里,就将本篇文章主题讲述完毕,核心是CrawlSpider,主要方法是rules。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2276749次
积分:18198
积分:18198
排名:第487名
原创:380篇
转载:180篇
评论:94条
文章:15篇
阅读:592889
阅读:4525
文章:27篇
阅读:53659
文章:47篇
阅读:361716
(20)(4)(11)(18)(45)(34)(56)(6)(15)(9)(50)(41)(28)(10)(31)(11)(28)(9)(15)(17)(16)(35)(30)(7)(1)(1)(12)CrawlSpiders
通过下面的命令可以快速创建 CrawlSpider模板 的代码:
scrapy genspider -t crawl
上一个案例中,我们通过正则表达式,制作了新的url作为Request请求参数,现在我们可以换个花样...
class scrapy.spiders.CrawlSpider
它是Spider的派生类,Spider类的设计原则是只爬取start_url列表中的网页,而CrawlSpider类定义了一些规则(rule)来提供跟进link的方便的机制,从爬取的网页中获取link并继续爬取的工作更适合。
CrawlSpider继承于Spider类,除了继承过来的属性外(name、allow_domains),还提供了一个新的属性和方法:
在rules中包含一个或多个Rule对象,每个Rule对爬取网站的动作定义了特定操作。如果多个rule匹配了相同的链接,则根据规则在本集合中被定义的顺序,第一个会被使用。
class scrapy.contrib.spiders.Rule(
link_extractor,
callback = None,
cb_kwargs = None,
follow = None,
process_links = None,
process_request = None
link_extractor:是一个Link Extractor对象,用于定义需要提取的链接。
callback: 从link_extractor中每获取到链接时,参数所指定的值作为回调函数,该回调函数接受一个response作为其第一个参数。
注意:当编写爬虫规则时,避免使用parse作为回调函数。由于CrawlSpider使用parse方法来实现其逻辑,如果覆盖了 parse方法,crawl spider将会运行失败。
follow:是一个布尔(boolean)值,指定了根据该规则从response提取的链接是否需要跟进。 如果callback为None,follow 默认设置为True ,否则默认为False。
process_links:指定该spider中哪个的函数将会被调用,从link_extractor中获取到链接列表时将会调用该函数。该方法主要用来过滤。
process_request:指定该spider中哪个的函数将会被调用, 该规则提取到每个request时都会调用该函数。 (用来过滤request)
parse_start_url(response):
当start_url的请求返回时,该方法被调用。
LinkExtractors
class scrapy.linkextractors.LinkExtractor
Link Extractors 的目的很简单: 提取链接?
每个LinkExtractor有唯一的公共方法是 extract_links(),它接收一个 Response 对象,并返回一个 scrapy.link.Link 对象。
Link Extractors要实例化一次,并且 extract_links 方法会根据不同的 response 调用多次提取链接?
classscrapy.contrib.linkextractors.sgml.SgmlLinkExtractor(
allow = (),
deny = (),
allow_domains = (),
deny_domains = (),
deny_extensions = None,
restrict_xpaths = (),
tags = ('a','area'),
attrs = ('href'),
canonicalize = True,
unique = True,
process_value = None
主要参数:
allow:满足括号中“正则表达式”的值会被提取,如果为空,则全部匹配。
deny:与这个正则表达式(或正则表达式列表)不匹配的URL一定不提取。
allow_domains:会被提取的链接的domains。
deny_domains:一定不会被提取链接的domains。
restrict_xpaths:使用xpath表达式,和allow共同作用过滤链接。
爬取规则(Crawling rules)
继续用腾讯招聘为例,给出配合rule使用CrawlSpider的例子:
scrapy shell "/position.php?&start=0#a"
导入LinkExtractor,创建LinkExtractor实例对象。:
from scrapy.linkextractors import LinkExtractor
page_lx = LinkExtractor(allow=('position.php?&start=\d+'))
allow : LinkExtractor对象最重要的参数之一,这是一个正则表达式,必须要匹配这个正则表达式(或正则表达式列表)的URL才会被提取,如果没有给出(或为空), 它会匹配所有的链接?
deny : 用法同allow,只不过与这个正则表达式匹配的URL不会被提取)?它的优先级高于 allow 的参数,如果没有给出(或None), 将不排除任何链接?
调用LinkExtractor实例的extract_links()方法查询匹配结果:
page_lx.extract_links(response)
没有查到:
注意转义字符的问题,继续重新匹配:
page_lx = LinkExtractor(allow=('position\.php\?&start=\d+'))
CrawlSpider版本
那么,scrapy shell测试完成之后,修改以下代码
这么写对吗?
不对!千万记住 callback 千万不能写 parse,再次强调:由于CrawlSpider使用parse方法来实现其逻辑,如果覆盖了 parse方法,crawl spider将会运行失败。
运行:&scrapy crawl tencent
Scrapy提供了log功能,可以通过 logging 模块使用。
可以修改配置文件settings.py,任意位置添加下面两行,效果会清爽很多。
LOG_FILE = "TencentSpider.log"
LOG_LEVEL = "INFO"
Log levels
Scrapy提供5层logging级别:
CRITICAL - 严重错误(critical)
ERROR - 一般错误(regular errors)
WARNING - 警告信息(warning messages)
INFO - 一般信息(informational messages)
DEBUG - 调试信息(debugging messages)
logging设置
通过在setting.py中进行以下设置可以被用来配置logging:
LOG_ENABLED&默认: True,启用logging
LOG_ENCODING&默认: 'utf-8',logging使用的编码
LOG_FILE&默认: None,在当前目录里创建logging输出文件的文件名
LOG_LEVEL&默认: 'DEBUG',log的最低级别
LOG_STDOUT&默认: False 如果为 True,进程所有的标准输出(及错误)将会被重定向到log中。例如,执行 print "hello" ,其将会在Scrapy log中显示。
阅读(...) 评论()

我要回帖

更多关于 python crawlspider 的文章

 

随机推荐