如何爬取一个网站的全站数据?

可以使用Scrapy中基于Spider的递归方式进行爬取(Request模块回调parse方法)

还有一种更高效的方法,就是基于CrawlSpider的自动爬取实现

简介

CrawlSpider其实是Spider的一个子类,除了继承到Spider的特性和功能外,还派生出了自己独有的强大功能和特性,其中最有名的就是"LInkExtractors"链接提取器,

Spider是所有爬虫的基类,其设计原则只是为了爬取start_url列表中的网页,但是使用从爬取的网页中提取出的url继续爬取的工作,CrawlSpider更加的合适。

创建示例

1 创建爬虫工程 scrapy startproject happy3

2 创建爬虫文件 scrapy genspider -t crawl demo www.qiushibaike.com

  -t crawl表示创建的爬虫文件是基于CrawlSpider这个类的而不是Spider基类(当然CrawlSpider也是基于Spider的)

可以看下demo.py

# -*- coding: utf-8 -*-
import scrapy
# 导入模块
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule # 可以它继承与CrawSpider
class DemoSpider(CrawlSpider):
name = 'demo'
allowed_domains = ['www.qiushibaike.com']
start_urls = ['http://www.qiushibaike.com/']
# 提取link的规则
rules = (
Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
)
# 解析方法
def parse_item(self, response):
i = {}
#i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract()
#i['name'] = response.xpath('//div[@id="name"]').extract()
#i['description'] = response.xpath('//div[@id="description"]').extract()
return i
LinkExtractor 链接提取器

主要作用是提取response中符合规则的链接。

每个LinkExtractor有唯一的公共方法是 extract_links(),它接收一个 Response 对象,并返回一个 scrapy.link.Link 对象

源码:

    def extract_links(self, response):
base_url = get_base_url(response)
if self.restrict_xpaths:
docs = [subdoc
for x in self.restrict_xpaths
for subdoc in response.xpath(x)]
else:
docs = [response.selector]
all_links = []
for doc in docs:
links = self._extract_links(doc, response.url, response.encoding, base_url)
all_links.extend(self._process_links(links))
return unique_list(all_links)

在上面代码中可以看到 LinkExtractor(allow=r'Items/'),它还有其他参数

allow=(),满足括号中的正则表达式则会被提取,如果为空,则全部匹配。

deny=(),与这个正则表达式(或正则表达式列表)不匹配的URL一定不提取。

allow_domains=(),会被提取链接的domains。

deny_domains=(),一定不会被提取链接的domains。

restrict_xpaths=(),使用xpath表达式,和allow共同作用过滤链接。

estrict_css=(),满足css表达式的值会被提取。

rule规则解析器

根据链接提取器中取到的链接,根据指定规则提取解析链接中的内容。

Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),

参数介绍:

  1 指定链接提取器

  2 指定解析数据的规则,是一个回调函数

  3 是否将链接提取器继续作用到链接提取器提取出的链接网页中,当callback为None,follow默认为true.

注意:当编写爬虫规则时,避免使用parse作为回调函数。由于CrawlSpider使用parse方法来实现其逻辑,如果覆盖了parse方法,爬虫会运行失败。

rules=()

对应不同的规则解析器,一个Rule对象表示一种提取规则。

CrawlSpider的整体流程

1 爬虫文件根据起始url,获取该url的网页内容。

2 链接提取器会根据指定提取规则将网页内容中的链接进行提取。

3 规则解析器会根据指定解析规则将链接提取器中取到的链接中网页内容,根据指定规则解析。

4 讲解析的数据分装到item中,然后交给管道进行持久化操作。

程序示例
# -*- coding: utf-8 -*-
import scrapy
# 导入模块
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule # 可以它继承与CrawSpider
class DemoSpider(CrawlSpider):
name = 'demo'
# allowed_domains = ['www.qiushibaike.com']
# 起始url,糗事百科的糗图
start_urls = ['http://www.qiushibaike.com/pic/']
# 提取link的规则
link = LinkExtractor(allow=r'/pic/$') # 提取第一页
link1 = LinkExtractor(allow=r'/pic/page/\d+\?') #其他页面
# rule中存放的是不同的解析规则的解析器
rules = (
Rule(link, callback='parse_item', follow=True),
Rule(link1, callback='parse_item', follow=True),
)
# 解析方法
def parse_item(self, response):
# i = {}
#i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract()
#i['name'] = response.xpath('//div[@id="name"]').extract()
#i['description'] = response.xpath('//div[@id="description"]').extract()
# return i
print(response)

我们可以看到它获取到了这些网站的url:

糗事百科糗图爬取保存到本地

demo.py

# -*- coding: utf-8 -*-
import scrapy
# 导入模块
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from happy3.items import Happy3Item # 可以它继承与CrawSpider
class DemoSpider(CrawlSpider):
name = 'demo'
# allowed_domains = ['www.qiushibaike.com']
# 起始url,糗事百科的糗图
start_urls = ['http://www.qiushibaike.com/pic/']
# 提取link的规则
link = LinkExtractor(allow=r'/pic/$') # 提取第一页
link1 = LinkExtractor(allow=r'/pic/page/\d+\?') #其他页面
# rule中存放的是不同的解析规则的解析器
rules = (
Rule(link, callback='parse_item', follow=True),
Rule(link1, callback='parse_item', follow=True),
)
# 解析方法
def parse_item(self, response):
div_list = response.xpath('//div[@id="content-left"]/div')
for one_div in div_list:
item = Happy3Item()
item['title'] = one_div.xpath('.//div[@class="content"]/span/text()').extract_first().strip('\n')
item['link'] = one_div.xpath('.//div[@class="thumb"]/a/img/@src').extract_first().strip('\n')
#i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract()
#i['name'] = response.xpath('//div[@id="name"]').extract()
#i['description'] = response.xpath('//div[@id="description"]').extract()
yield item

item.py

import scrapy

class Happy3Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field()
link = scrapy.Field()

pipelines.py

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

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
from scrapy.pipelines.images import ImagesPipeline
from scrapy.spiders import Request
import os # 记录下载记录
class Happy3Pipeline(object): def create_dir(self, path):
path = path.strip()
if not os.path.exists(path):
os.mkdir(path) def process_item(self, item, spider):
# 让标题里只保留汉字 # 文件夹名字
apath = './pic/' + ''.join([ i for i in (item['title'])[0:15] if i >= u'\u4e00' and i <= u'\u9fa5'])
# 里面的title的txt文件名字
file_name = (apath + '/' + item['link'].split('/')[-1]).replace('jpg', 'txt')
# 创建文件夹
self.create_dir(apath)
with open(file_name, 'w', encoding='utf-8') as f:
f.write(item['title'])
return item # 下载图片
class QiushiImagePipeline(ImagesPipeline):
def file_path(self, request, response=None, info=None):
item = request.meta['item']
apath = ''.join([ i for i in (item['title'])[0:15] if i >= u'\u4e00' and i <= u'\u9fa5'])
img_name = item['link'].split('/')[-1]
path = apath + '/' + img_name
return path def get_media_requests(self, item, info):
url = ['https:' + item['link']]
print(url)
return Request(url=url[0], meta={'item':item})

settings.py

BOT_NAME = 'happy3'

SPIDER_MODULES = ['happy3.spiders']
NEWSPIDER_MODULE = 'happy3.spiders' # Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1' # Obey robots.txt rules
ROBOTSTXT_OBEY = False # Configure maximum concurrent requests performed by Scrapy (default: 16)
CONCURRENT_REQUESTS = 100
DOWNLOAD_DELAY = 1
ITEM_PIPELINES = {
'happy3.pipelines.Happy3Pipeline': 300,
'happy3.pipelines.QiushiImagePipeline':400,
}
IMAGES_STORE = 'pic'

得到结果:

大概630张图吧,自己练习的话可以少加载点网页。

爬虫框架之Scrapy(三 CrawlSpider)的更多相关文章

  1. 06 爬虫框架:scrapy

    爬虫框架:scrapy   一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前S ...

  2. 九、爬虫框架之Scrapy

    爬虫框架之Scrapy 一.介绍 二.安装 三.命令行工具 四.项目结构以及爬虫应用简介 五.Spiders 六.Selectors 七.Items 八.Item Pipelin 九. Dowload ...

  3. Python-S9-Day125-Web微信&爬虫框架之scrapy

    01 今日内容概要 02 内容回顾:爬虫 03 内容回顾:网络和并发编程 04 Web微信之获取联系人列表 05 Web微信之发送消息 06 为什么request.POST拿不到数据 07 到底使用j ...

  4. Golang 网络爬虫框架gocolly/colly 三

    Golang 网络爬虫框架gocolly/colly 三 熟悉了<Golang 网络爬虫框架gocolly/colly一>和<Golang 网络爬虫框架gocolly/colly二& ...

  5. 洗礼灵魂,修炼python(72)--爬虫篇—爬虫框架:Scrapy

    题外话: 前面学了那么多,相信你已经对python很了解了,对爬虫也很有见解了,然后本来的计划是这样的:(请忽略编号和日期,这个是不定数,我在更博会随时改的) 上面截图的是我的草稿 然后当我开始写博文 ...

  6. 爬虫框架之Scrapy

    一.介绍 二.安装 三.命令行工具 四.项目结构以及爬虫应用简介 五.Spiders 六.Selectors 七.Items 八.Item Pipelin 九. Dowloader Middeware ...

  7. 爬虫框架:scrapy

    一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前Scrapy的用途十分广泛,可 ...

  8. Scrapy爬虫框架补充内容三(代理及其基本原理介绍)

    前言:(本文参考维基百科及百度百科所写) 当我们使用爬虫抓取数据时,有时会产生错误比如:突然跳出来了403 Forbidden 或者网页上出现以下提示:您的ip访问频率太高 或者时不时跳出一个验证码需 ...

  9. 爬虫框架之Scrapy(四 ImagePipeline)

    ImagePipeline 使用scrapy框架我们除了要下载文本,还有可能需要下载图片,scrapy提供了ImagePipeline来进行图片的下载. ImagePipeline还支持以下特别的功能 ...

随机推荐

  1. Enabling Chrome Developer Tools inside Postman

    Chrome's Developer Tools are an indispensable part of the modern web development workflow. However, ...

  2. java之集合Collection 详解之4

    package cn.itcast_04; public class Student { private String name; private int age; public Student() ...

  3. sublime安装AngularJS插件

    sublime能够支持AngularJS开发那绝对是一件很爽的事情.下面我一步步讲解如何为sublime安装AngularJS插件. 1.添加控制包站点 根据你安装sublime 版本不同,在控制台写 ...

  4. celery学习笔记2

    1.定义: Celery是一个异步的任务队列(也叫做分布式任务队列) 2.工作结构 Celery分为3个部分 (1)worker部分负责任务的处理,即工作进程(我的理解工作进程就是你写的python代 ...

  5. 如何添加“在这里打开PowerShell”到Windows中的上下文菜单

    It was only a matter of time, right? Due to my recent infatuation passionate love affair with PowerS ...

  6. ArrayBlockingQueue简介

    ArrayBlockingQueue基于数组,先进先出,从尾部插入到队列,从头部开始返回. 线程安全的有序阻塞队列,内部通过"互斥锁"保护竞争资源. 指定时间的阻塞读写 容量可限制 ...

  7. BZOJ_3048_[Usaco2013 Jan]Cow Lineup _双指针

    BZOJ_3048_[Usaco2013 Jan]Cow Lineup _双指针 Description Farmer John's N cows (1 <= N <= 100,000) ...

  8. Java异常简介、异常捕获还是上抛总结

    概要 本章对Java中的异常进行介绍.内容包括:1.Java异常简介2.Java异常框架 一.Java异常简介 Java异常是Java提供的一种识别及响应错误的一致性机制. Java异常机制可以使程序 ...

  9. ISCC 2018(数字密文)

    做过iscc 2018之后有了很多的感触,也有更多的了解自己的不足之处,整理了一下web的wp, 为了保证各位小伙伴的阅读质量,我将会把wp以每一道题一个博文的形式写出来,希望能够帮助到你们 其中的步 ...

  10. SpringBoot(三)_controller的使用

    针对controller 中 如何使用注解进行解析 @RestController 返回数据类型为 Json 字符串,特别适合我们给其他系统提供接口时使用. @RequestMapping (1) 不 ...