python爬虫入门(七)Scrapy框架之Spider类

python

 Spider类

Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。

换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。

class scrapy.Spider是最基本的类,所有编写的爬虫必须继承这个类。

主要用到的函数及调用顺序为:

__init__() : 初始化爬虫名字和start_urls列表

start_requests() 调用make_requests_from url():生成Requests对象交给Scrapy下载并返回response

parse() : 解析response,并返回Item或Requests(需指定回调函数)。Item传给Item pipline持久化 , 而Requests交由Scrapy下载,并由指定的回调函数处理(默认parse()),一直进行循环,直到处理完所有的数据为止。

源码参考

#所有爬虫的基类,用户定义的爬虫必须从这个类继承

class Spider(object_ref):

#定义spider名字的字符串(string)。spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。

#name是spider最重要的属性,而且是必须的。

#一般做法是以该网站(domain)(加或不加 后缀 )来命名spider。 例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite

name = None

#初始化,提取爬虫名字,start_ruls

def __init__(self, name=None, **kwargs):

if name is not None:

self.name = name

# 如果爬虫没有名字,中断后续操作则报错

elif not getattr(self, 'name', None):

raise ValueError("%s must have a name" % type(self).__name__)

# python 对象或类型通过内置成员__dict__来存储成员信息

self.__dict__.update(kwargs)

#URL列表。当没有指定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。

if not hasattr(self, 'start_urls'):

self.start_urls = []

# 打印Scrapy执行后的log信息

def log(self, message, level=log.DEBUG, **kw):

log.msg(message, spider=self, level=level, **kw)

# 判断对象object的属性是否存在,不存在做断言处理

def set_crawler(self, crawler):

assert not hasattr(self, '_crawler'), "Spider already bounded to %s" % crawler

self._crawler = crawler

@property

def crawler(self):

assert hasattr(self, '_crawler'), "Spider not bounded to any crawler"

return self._crawler

@property

def settings(self):

return self.crawler.settings

#该方法将读取start_urls内的地址,并为每一个地址生成一个Request对象,交给Scrapy下载并返回Response

#该方法仅调用一次

def start_requests(self):

for url in self.start_urls:

yield self.make_requests_from_url(url)

#start_requests()中调用,实际生成Request的函数。

#Request对象默认的回调函数为parse(),提交的方式为get

def make_requests_from_url(self, url):

return Request(url, dont_filter=True)

#默认的Request对象回调函数,处理返回的response。

#生成Item或者Request对象。用户必须实现这个类

def parse(self, response):

raise NotImplementedError

@classmethod

def handles_request(cls, request):

return url_is_from_spider(request.url, cls)

def __str__(self):

return "<%s %r at 0x%0x>" % (type(self).__name__, self.name, id(self))

__repr__ = __str__

主要属性和方法

name

定义spider名字的字符串。

例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite

allowed_domains

包含了spider允许爬取的域名(domain)的列表,可选。

start_urls

初始URL元祖/列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。

start_requests(self)

该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取(默认实现是使用 start_urls 的url)的第一个Request。

当spider启动爬取并且未指定start_urls时,该方法被调用。

parse(self, response)

当请求url返回网页没有指定回调函数时,默认的Request对象回调函数。用来处理网页返回的response,以及生成Item或者Request对象。

Scrapy框架爬取--->>>腾讯招聘的所有职位信息

 1.先分析腾讯招聘网站url

第一页:https://hr.tencent.com/position.php?&start=0#a

第二页:https://hr.tencent.com/position.php?&start=10#a

第三页:https://hr.tencent.com/position.php?&start=20#a

 发现有的职位类别为空,所有在找职位类别的时候空值也要加进去,否则for循环取不到值会直接退出了 ./td[2]/text()|./td[2]

2.目录结构

3.items.py

# -*- coding: utf-8 -*-
import scrapy

class TencentItem(scrapy.Item):

# 职位名

positionname = scrapy.Field()

# 详情连接

positionlink = scrapy.Field()

# 职位类别

positionType = scrapy.Field()

# 招聘人数

peopleNum = scrapy.Field()

# 工作地点

workLocation = scrapy.Field()

# 发布时间

publishTime = scrapy.Field()

4.tencentPosition.py

tencentPosition.py用命令创建 scrapy genspider tencentPosition "tencent.com"

# -*- coding: utf-8 -*-

import scrapy

from tencent.items import TencentItem

class TencentpositionSpider(scrapy.Spider):

name = "tencent"

allowed_domains = ["tencent.com"]

url = "http://hr.tencent.com/position.php?&start="

offset = 0

start_urls = [url + str(offset)]

def parse(self, response):

for each in response.xpath("//tr[@class='even'] | //tr[@class='odd']"):

# 初始化模型对象

item = TencentItem()

       # 职位名称

item['positionname'] = each.xpath("./td[1]/a/text()").extract()[0]

# 详情连接

item['positionlink'] = each.xpath("./td[1]/a/@href").extract()[0]

# 职位类别

item['positionType'] = each.xpath("./td[2]/text()|./td[2]").extract()[0]

# 招聘人数

item['peopleNum'] = each.xpath("./td[3]/text()").extract()[0]

# 工作地点

item['workLocation'] = each.xpath("./td[4]/text()").extract()[0]

# 发布时间

item['publishTime'] = each.xpath("./td[5]/text()").extract()[0]

yield item

if self.offset < 3171:

self.offset += 10

# 每次处理完一页的数据之后,重新发送下一页页面请求

# self.offset自增10,同时拼接为新的url,并调用回调函数self.parse处理Response

yield scrapy.Request(self.url + str(self.offset), callback = self.parse)

5.pipelines.py

# -*- coding: utf-8 -*-

import json

class TencentPipeline(object):

def __init__(self):

self.filename = open("tencent.json", "w")

def process_item(self, item, spider):

text = json.dumps(dict(item), ensure_ascii = False) + ",\n"

self.filename.write(text.encode("utf-8"))

return item

def close_spider(self, spider):

self.filename.close()

6.settings.py里面的设置

ROBOTSTXT_OBEY = True

DOWNLOAD_DELAY = 4 #防止爬取过快丢失数据

DEFAULT_REQUEST_HEADERS = {

"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;",

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'

}

ITEM_PIPELINES = {

'tencent.pipelines.TencentPipeline': 300,

}

爬取的结果

 

 

 

 Spider类

Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。

换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。

class scrapy.Spider是最基本的类,所有编写的爬虫必须继承这个类。

主要用到的函数及调用顺序为:

__init__() : 初始化爬虫名字和start_urls列表

start_requests() 调用make_requests_from url():生成Requests对象交给Scrapy下载并返回response

parse() : 解析response,并返回Item或Requests(需指定回调函数)。Item传给Item pipline持久化 , 而Requests交由Scrapy下载,并由指定的回调函数处理(默认parse()),一直进行循环,直到处理完所有的数据为止。

源码参考

#所有爬虫的基类,用户定义的爬虫必须从这个类继承

class Spider(object_ref):

#定义spider名字的字符串(string)。spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。

#name是spider最重要的属性,而且是必须的。

#一般做法是以该网站(domain)(加或不加 后缀 )来命名spider。 例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite

name = None

#初始化,提取爬虫名字,start_ruls

def __init__(self, name=None, **kwargs):

if name is not None:

self.name = name

# 如果爬虫没有名字,中断后续操作则报错

elif not getattr(self, 'name', None):

raise ValueError("%s must have a name" % type(self).__name__)

# python 对象或类型通过内置成员__dict__来存储成员信息

self.__dict__.update(kwargs)

#URL列表。当没有指定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。

if not hasattr(self, 'start_urls'):

self.start_urls = []

# 打印Scrapy执行后的log信息

def log(self, message, level=log.DEBUG, **kw):

log.msg(message, spider=self, level=level, **kw)

# 判断对象object的属性是否存在,不存在做断言处理

def set_crawler(self, crawler):

assert not hasattr(self, '_crawler'), "Spider already bounded to %s" % crawler

self._crawler = crawler

@property

def crawler(self):

assert hasattr(self, '_crawler'), "Spider not bounded to any crawler"

return self._crawler

@property

def settings(self):

return self.crawler.settings

#该方法将读取start_urls内的地址,并为每一个地址生成一个Request对象,交给Scrapy下载并返回Response

#该方法仅调用一次

def start_requests(self):

for url in self.start_urls:

yield self.make_requests_from_url(url)

#start_requests()中调用,实际生成Request的函数。

#Request对象默认的回调函数为parse(),提交的方式为get

def make_requests_from_url(self, url):

return Request(url, dont_filter=True)

#默认的Request对象回调函数,处理返回的response。

#生成Item或者Request对象。用户必须实现这个类

def parse(self, response):

raise NotImplementedError

@classmethod

def handles_request(cls, request):

return url_is_from_spider(request.url, cls)

def __str__(self):

return "<%s %r at 0x%0x>" % (type(self).__name__, self.name, id(self))

__repr__ = __str__

主要属性和方法

name

定义spider名字的字符串。

例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite

allowed_domains

包含了spider允许爬取的域名(domain)的列表,可选。

start_urls

初始URL元祖/列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。

start_requests(self)

该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取(默认实现是使用 start_urls 的url)的第一个Request。

当spider启动爬取并且未指定start_urls时,该方法被调用。

parse(self, response)

当请求url返回网页没有指定回调函数时,默认的Request对象回调函数。用来处理网页返回的response,以及生成Item或者Request对象。

Scrapy框架爬取--->>>腾讯招聘的所有职位信息

 1.先分析腾讯招聘网站url

第一页:https://hr.tencent.com/position.php?&start=0#a

第二页:https://hr.tencent.com/position.php?&start=10#a

第三页:https://hr.tencent.com/position.php?&start=20#a

 发现有的职位类别为空,所有在找职位类别的时候空值也要加进去,否则for循环取不到值会直接退出了 ./td[2]/text()|./td[2]

2.目录结构

3.items.py

# -*- coding: utf-8 -*-
import scrapy

class TencentItem(scrapy.Item):

# 职位名

positionname = scrapy.Field()

# 详情连接

positionlink = scrapy.Field()

# 职位类别

positionType = scrapy.Field()

# 招聘人数

peopleNum = scrapy.Field()

# 工作地点

workLocation = scrapy.Field()

# 发布时间

publishTime = scrapy.Field()

4.tencentPosition.py

tencentPosition.py用命令创建 scrapy genspider tencentPosition "tencent.com"

# -*- coding: utf-8 -*-

import scrapy

from tencent.items import TencentItem

class TencentpositionSpider(scrapy.Spider):

name = "tencent"

allowed_domains = ["tencent.com"]

url = "http://hr.tencent.com/position.php?&start="

offset = 0

start_urls = [url + str(offset)]

def parse(self, response):

for each in response.xpath("//tr[@class='even'] | //tr[@class='odd']"):

# 初始化模型对象

item = TencentItem()

       # 职位名称

item['positionname'] = each.xpath("./td[1]/a/text()").extract()[0]

# 详情连接

item['positionlink'] = each.xpath("./td[1]/a/@href").extract()[0]

# 职位类别

item['positionType'] = each.xpath("./td[2]/text()|./td[2]").extract()[0]

# 招聘人数

item['peopleNum'] = each.xpath("./td[3]/text()").extract()[0]

# 工作地点

item['workLocation'] = each.xpath("./td[4]/text()").extract()[0]

# 发布时间

item['publishTime'] = each.xpath("./td[5]/text()").extract()[0]

yield item

if self.offset < 3171:

self.offset += 10

# 每次处理完一页的数据之后,重新发送下一页页面请求

# self.offset自增10,同时拼接为新的url,并调用回调函数self.parse处理Response

yield scrapy.Request(self.url + str(self.offset), callback = self.parse)

5.pipelines.py

# -*- coding: utf-8 -*-

import json

class TencentPipeline(object):

def __init__(self):

self.filename = open("tencent.json", "w")

def process_item(self, item, spider):

text = json.dumps(dict(item), ensure_ascii = False) + ",\n"

self.filename.write(text.encode("utf-8"))

return item

def close_spider(self, spider):

self.filename.close()

6.settings.py里面的设置

ROBOTSTXT_OBEY = True

DOWNLOAD_DELAY = 4 #防止爬取过快丢失数据

DEFAULT_REQUEST_HEADERS = {

"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;",

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'

}

ITEM_PIPELINES = {

'tencent.pipelines.TencentPipeline': 300,

}

爬取的结果

以上是 python爬虫入门(七)Scrapy框架之Spider类 的全部内容, 来源链接: utcz.com/z/387317.html

回到顶部