内容简介:一:概述深度爬虫:针对其实url地址进行数据采集,在响应数据中进行数据筛选得到需要进行数据采集的下一波url地址,并将url地址添加到数据采集队列中进行二次爬取,以此类推深度爬虫可以通过不同的方式实现,在urllib2和requesets模块中通过轮询数据筛选得到目标url地址,然后进行循环爬取数据即可,在scrapy中主要通过两种方式进行处理:
编辑推荐: |
本文来源博客园,本文主要介绍了深度爬虫的应用,通过Response对象和Request完成深度数据采集和深度爬取,希望对您的学习有所帮助。 |
一:概述深度爬虫:
针对其实url地址进行数据采集,在响应数据中进行数据筛选得到需要进行数据采集的下一波url地址,并将url地址添加到数据采集队列中进行二次爬取,以此类推
深度爬虫可以通过不同的方式实现,在urllib2和requesets模块中通过轮询数据筛选得到目标url地址,然后进行循环爬取数据即可,在scrapy中主要通过两种方式进行处理:
1.通过Response对象的地址序列和Request对象的请求处理完成深度采集
2.通过CrawlSpider类型中的请求链接提取规则自动进行深度数据采集处理
二:深度爬虫的应用
1.通过Response对象和Request完成深度数据采集Request对象:
#Request底层源码
# scrapy中的Request请求对象
# 默认构建时,method="GET"包装的是GET请求的采集方式
# 参数url:请求地址字符串
# 参数callback:请求的回调函数
# 参数headers:默认的请求头
# 参数body: 请求体
# 参数cookies:请求中包含的cookie对象
# 参数encoding:请求编码方式
def __init__(self, url, callback=None, method='GET', headers=None, body=None,
cookies=None, meta=None, encoding='utf-8', priority=0,
dont_filter=False, errback=None, flags=None):
self._encoding = encoding # this one has to be set first
self.method = str(method).upper()
self._set_url(url)
self._set_body(body)
assert isinstance(priority, int), "Request priority not an integer: %r" % priority
self.priority = priority
if callback is not None and not callable(callback):
raise TypeError('callback must be a callable, got %s' % type(callback).__name__)
if errback is not None and not callable(errback):
raise TypeError('errback must be a callable, got %s' % type(errback).__name__)
assert callback or not errback, "Cannot use errback without a callback"
self.callback = callback
self.errback = errback
self.cookies = cookies or {}
self.headers = Headers(headers or {}, encoding=encoding)
self.dont_filter = dont_filter
self._meta = dict(meta) if meta else None
self.flags = [] if flags is None else list(flags)
get请求
import scrapy #get请求 class GetSpider(scrapy.Spider): #一般情况下爬虫默认的为get请求方式 #定义爬虫名称 name = 'getspider' #定义限制访问域名 allowed_domains = ['baidu.com'] #定义起始url地址 start_urls = [ 'http://www.baidu.com' ] def parse(self, response): #进行响应数据的处理 ''' 起始请求的数据采集,由scrapy框架自动完成 爬虫——起始地址url ——scrapy.Spider——Request()请求 :param response: :return: ''' pass
post请求
#post请求 class PostSpider(scrapy.Spider): ''' post请求操作爬虫 ''' name = 'postspider' allowed_domains = ['renren.com'] start_urls = [ 'http://www.renren.com/login' ] def start_requests(self): ''' 重写start_requests()函数,发送自定义请求 :return: ''' return scrapy.FormRequest( self.start_urls[0], formdata={'username':'admin', 'password':123456}, callback=self.parse_response ) def parse_response(self, response): #用来专门处理post请求得到的响应数据 pass ps:由于scrapy框架默认的Request是get请求,想要发送post的请求,需要重写start_requests()函数覆盖父类中原有的请求方法 **Response对象在项目中直接操作的并不是很多
小结
案例操作:深度爬取xx招聘网站的xx岗位信息
#1.创建项目
scrapy startproject myspider
#2.分析请求地址页面,想要获取的数据,定义字段,封装item对象 # -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # https://doc.scrapy.org/en/latest/topics/items.html import scrapy #分析字段 job = 工作名称 company = 公司名称 salary = 薪水 class ZhilianItem(scrapy.Item): #定义属性字段 job = scrapy.Field() company = scrapy.Field() salary = scrapy.Field()
#3.创建数据库表来存储数据 create table jobs( id int auto_increment primary key, job varchar(200), company varchar(200), salary = varchar(50) );
#4.开发爬虫程序 # -*- coding:utf-8 -*- import scrapy from .. import items class ZhiLian(scrapy.Spider): #定义爬虫的名称,用于在命令中调用 name = 'zl' #定义域名限制,只能爬取xxx域名下的数据 allowed_domains = ['zhaopin.com'] #定义url地址 start_urls =( 'http://sou.zhaopin.com/jobs/searchresult.ashx?jl =%E5%8C%97%E4%BA%AC&kw=%E7%88%AC%E8%99%AB&sm=0&p=1', ) def parse(self, response): ''' 采集到数据后,自动执行的函数,主要进行如下功能 数据筛选——》封装Item对象——》传递数据给Pipelines 采集到的数据封装在response ''' #提取所有的工信息列表selecor列表 job_list = response.xpath("//div[@id='newlist_list _content_table']/table[position()>1]/tr[1]") for select in job_list: job = select.xpath("td[@class='zwmc']/div/a").xpath ('string(.)').extract()[0] company = select.xpath("td[@class='gsmc'] /a/text()").extract()[0] salary = select.xpath("td[@class='zwyx'] /text()").extract()[0] print job print company print salary #封 装成item对象 item = items.ZhilianItem() item['job'] = job item['company'] = company item['salary'] = salary #将本次生成的item对象交给pipeline进行处理 yield item #深度采集,爬取下一页 page_list = response.xpath('//div[@class= "pagesDown"]/ul/li/a/@href').extract() print ('################') print page_list print ('################') for next_page in page_list: next_page = response.urljoin(next_page) yield scrapy.Request(next_page, callback=self.parse)
#5.数据处理:开发管道模块
在pipelines.py模块中定义处理Item数据的pipelines,
将数据存储到数据库中
#导入数据库引擎对象
from sqlalchemy import create_engine
#导入会话构建对象
from sqlalchemy.orm import sessionmaker
#替换MySQldb模块
import pymysql
pymysql.install_as_MySQLdb()
class ZhilianPipeline(object):
#处理智联招聘数据的pipeline,负责最终的数据验证和数据存储
def __init__(self):
'''
初始化对象数据:可以用于初始化资源
如:打开文件,打开数据库连接等操作
'''
#创建连接数据库引擎
self.engine = create_engine('mysql://root:123456@localhost
/spider_zhilian?charset=utf8')
Session = sessionmaker(bind=self.engine)
self.session = Session()
def open_spider(self, spider):
'''
爬虫开启时需要调用函数,经常用于数据的初始化
:param spider:
:return:
'''
pass
def close_spider(self,spider):
'''
爬虫程序自动关闭时调用函数
经常用于做一些资源回收工作,如关闭和数据库的连接
:return:
'''
self.session.close()
def process_item(self, item, spider):
'''
该函数会在爬虫采集并封装好的Item对象时自动调用
函数针对item数据进行验证和存储
:param item:
:param spider:
:return:
'''
#定义 sql 语句
sql = 'insert into job(job, company, salary) values( "%s", "%s", "%s")'\
% (item['job'], item['company'], item['salary'])
#执行sql语句
self.session.execute(sql)
#提交数据
self.session.commit()
#6.在setting.py设置模块中注册pipeline ITEM_PIPELINES = { # 'myspider.pipelines.MyspiderPipeline': 300, 'myspider.pipelines.ZhilianPipeline': 300, }
#7.启动项目
命令行:scrapy crawl zl
2.Spider CrawlSpider完成数据深度爬取
scrapy框架对于深度爬虫,提供了一种封装类scrapy.CrawlSpider,当我们开发时继承这个类,就能使用scrapy框架封装好的各种深度爬虫功能
scrapy.CrawlSpider是从scrapy.Spider继承并进行功能扩展的类,主要通过定义url地址提取规则,跟踪链接地址,从而进行深度的数据采集
(1).查看CrawlSpider的部分源码,可以帮助你理解
class CrawlSpider(Spider): rules = () def __init__(self, *a, **kw): super(CrawlSpider, self).__init__(*a, **kw) self._compile_rules() # 1. 调用重写父类的parse()函数来处理start_urls中返回的response对象 # 2. parse()则将这些response对象再次传递给了_parse_response()函数处理 # 2.1. _parse_response()函数中设置follow为True,该参数用于打开是否跟进链接提取 # 3. parse将返回item和跟进了的Request对象 def parse(self, response): return self._parse_response(response, self.parse_start_url, cb_kwargs={}, follow=True) # 定义处理start_url中返回的response的函数,需要重写 def parse_start_url(self, response): return [] # 结果过滤函数 def process_results(self, response, results): return results # 从response中抽取符合任一用户定义'规则'的链接,并构造成Resquest对象返回 def _requests_to_follow(self, response): if not isinstance(response, HtmlResponse): return seen = set() # 循环获取定义的url地址提取规则 for n, rule in enumerate(self._rules): # 得到所有的提取规则列表 links = [l for l in rule.link_extractor.extract_links(response) if l not in seen] # 使用用户指定的process_links处理每个连接 if links and rule.process_links: links = rule.process_links(links) #将链接加入seen集合,为每个链接生成Request对象,并设置回调函数为_repsonse_downloaded() for link in links: seen.add(link) # 构造Request对象,并将Rule规则中定义的回调函数作为这个Request对象的回调函数 r = Request(url=link.url, callback=self._response_downloaded) r.meta.update(rule=n, link_text=link.text) # 对每个Request调用process_request()函数。该函数默认为indentify,即不做任何处理,直接返回该Request. yield rule.process_request(r) # 采集数据链接处理,从符合规则的rule中提取链接并返回item和request def _response_downloaded(self, response): rule = self._rules[response.meta['rule']] return self._parse_response(response, rule.callback, rule.cb_kwargs, rule.follow) # 解析response对象,通过callback回调函数解析处理,并返回request或Item对象 def _parse_response(self, response, callback, cb_kwargs, follow=True): # 首先判断是否设置了回调函数。(该回调函数可能是rule中的解析函数,也可能是 parse_start_url函数) #如果设置了回调函数(parse_start_url()),那么首先用parse_start_url()处理response对象, # 然后再交给process_results处理。返回cb_res的一个列表 if callback: #如果是parse调用的,则会解析成Request对象 #如果是rule callback,则会解析成Item cb_res = callback(response, **cb_kwargs) or () cb_res = self.process_results(response, cb_res) for requests_or_item in iterate_spider_output(cb_res): yield requests_or_item # 如果需要跟进,那么使用定义的Rule规则提取并返回这些Request对象 if follow and self._follow_links: #返回每个Request对象 for request_or_item in self._requests_to_follow(response): yield request_or_item # 规则过滤 def _compile_rules(self): def get_method(method): if callable(method): return method elif isinstance(method, basestring): return getattr(self, method, None) self._rules = [copy.copy(r) for r in self.rules] for rule in self._rules: rule.callback = get_method(rule.callback) rule.process_links = get_method(rule.process_links) rule.process_request = get_method(rule.process_request) # 链接跟踪全局配置设置 def set_crawler(self, crawler): super(CrawlSpider, self).set_crawler(crawler) self._follow_links = crawler.settings.getbool('CRAWLSPIDER_FOLLOW_LINKS', True)
(2).LinkExtractor链接提取对象:主要目的用于定义链接提取匹配方式
class scrapy.linkextractors.LinkExtractor( allow = (), # 正则表达式,符合规则的链接会提取 deny = (), # 正则表达式,负责规则的链接会排除 allow_domains = (), # 允许的域名 deny_domains = (), # 禁止的域名 deny_extensions = None, # 是否允许扩展 restrict_xpaths = (), # xpath表达式,和allow配合使用精确提取数据 tags = ('a','area'), # 标签~ attrs = ('href'), # 指定提取的属性 canonicalize = True, unique = True, # 唯一约束,是否去重 process_value = None ) ps:我们可以在终端命令执行 scrapy shell + url地址 测试url地址是否有效 # 导入LinkExtractor类型 >>> from linkextractors import LinkExtractor # 定义提取规则,包含指定字符的链接被提取 >>> links = LinkExtractor(allow=('7624f24&p=\d+')) #从响应数据中提取符合规则的超链接,执行extract_links()函数 next_urls = links.extract_links(response)
(3).Rule规则对象:链接操作规则对象,主要定义对于LinkExtractor类型提取的超链接url地址操作行为,一个爬虫可以有多个Rule对象,包含在rules列表中即可
class scrapy.spiders.Rule( # LinkExtractor对象 link_extractor, # 回调函数,得到数据库之后调用的函数 callback = None, # 回调函数调用时传递的参数列表 cb_kwargs = None, # 是否从返回的响应数据中根据LinkExtractor继续提取,一般选择True follow = None, # 从LinkExtractor中提取的连接,会自动调用该选项指定的函数,用来进行超链接的筛选 process_links = None, # 指定每个请求封装处理时要调用的函数 process_request = None )
(4).实战演练:爬取招聘信息
#1.创建项目
scrapy startproject myspider2
#2.分析请求地址页面,想要获取的数据,定义字段,封装item对象 # -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # https://doc.scrapy.org/en/latest/topics/items.html import scrapy #分析字段 job = 工作名称 company = 公司名称 salary = 薪水 class ZhilianItem(scrapy.Item): #定义属性字段 job = scrapy.Field() company = scrapy.Field() salary = scrapy.Field()
#3.爬虫程序开发 ''' 基于scrapy.spider.CrawlSpider的深度爬虫操作 ''' #引入模块 from scrapy.spider import CrawlSpider, Rule #引入链接提取模块 from scrapy.linkextractors import LinkExtractor from .. items import ZhaopinItem class ZhaopinSpider(CrawlSpider): #定义爬虫名称 name = 'zp' #限制域名 allowed_domains = ['zhaopin.com'] #定义起始url地址 start_urls = [ "http://sou.zhaopin.com/jobs/searchresult.ashx? jl=%E5%8C%97%E4%BA%AC%2b%E4%B8%8A%E6%B5%B7%2b%E5%B9%BF %E5%B7%9E%2b%E6%B7%B1%E5%9C%B3&kw=python&isadv=0&sg= 7cd76e75888443e6b906df8f5cf121c1&p=1", ] #定义链接提取规则:根据url地址分析得到 link_extractor = LinkExtractor( allow = (r"e75888443e6b906df8f5cf121c1&p=\d+") ) #定义链接操作规则 rules = [ Rule(link_extractor, follow = True, callback = 'parse_response'), ] #注意:在这里不能重写parse()函数,因为父类中已经 重写过parse()函数,如果我们再次重写该函数,深度采集数据就会失效 #处理响应数据 def parse_response(self, response): #提取当前页面所有需要的数据 job_list = response.xpath("//div[@id='newlist_list_content_table'] /table[position()>1]/tr[1]") for jobs in job_list: job = jobs.xpath("td[@class='zwmc']/div/a").xpath ("string(.)").extract()[0] company = jobs.xpath("td[@class='gsmc']/a/text()"). extract()[0] salary = jobs.xpath("td[@class='zwyx']/text()").extract()[0] print(job) print(company) print(salary) ps:这里我们已经取到了想要的数据了,只是没有存储到数据库里、 其实数据存储跟上面的案例数据存储方式一样,可以直接copy过来使用
#4.启动项目
scrapy crawl zp
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 深度操作系统 20 正式版发布
- 深度操作系统 deepin 20.2 发布
- 深度操作系统 Deepin 20 BETA 发布
- 深度操作系统 15.6 —— 细节中寻求突破
- 深度操作系统 deepin 20.1 (1010) 发布
- 深度操作系统 deepin 20.2.1 发布
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
汇编语言(第2版)
王爽 / 清华大学出版社 / 2008-4 / 33.00元
《汇编语言(第2版)》是各种CPU提供的机器指令的助记符的集合,人们可以用汇编语言直接控制硬件系统进行工作。汇编语言是很多相关课程(如数据结构、操作系统、微机原理等)的重要基础。为了更好地引导、帮助读者学习汇编语言,作者以循序渐进的思想精心创作了《汇编语言(第2版)》。《汇编语言(第2版)》具有如下特点:采用了全新的结构对课程的内容进行组织,对知识进行最小化分割,为读者构造了循序渐进的学习线索;在......一起来看看 《汇编语言(第2版)》 这本书的介绍吧!