Scrapy爬虫框架学习
一、Scrapy框架简介
- 1. 下载页面
- 2. 解析
- 3. 并发
- 4. 深度
二、安装
- linux下安装
- pip3 install scrapy
- windows下安装
- a.pip3 install wheel
- b.下载twisted和pywin32 http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
- c.进入下载目录
- 执行pip3 install Twisted-18.7.0-cp36-cp36m-win_amd64.whl #cp36为适合python3.6
- 执行pip3 install pywin32-224-cp36-cp36m-win_amd64.whl
- d.pip3 install scrapy
- e.下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/ #找到适合本机python版本的64位
三、Scrapy整体架构图
3.1 Scrapy使用Twisted异步网络库来处理网络通讯
3.2 各个主要文件说明
spiders(蜘蛛)文件夹:如ip138.com
- name #不能省略,最好不要修改
- starts_urls #起始url
- allowed_domains #爬取允许域名列表,起始url不受影响。网页中的外链受此限制
四、基本使用
- 1. 指定初始url
- 2. 解析器响应内容
- - 给调度器
- - 给item:pipeline;用于做格式化;持久化
- 基本步骤:
- a:scrapy startproject 项目名 #创建项目
- b:进入项目目录
- c:scrapy genspider baidu www.baidu.com #创建start_url
- d:打开项目名\spiders\baidu.py进行编辑
- e:scrapy crawl baidu #执行,加--nolog可以不显示日志,如果没有内容显示,可能此IP已经有防爬机制,可换个不知名ip试试
五、筛选器
5.1 Selector介绍
在scrapy中,可以使用Selector筛选器,代替BeautifulSoup
在scrapy项目里的spiders文件里的baidu.py爬虫文件编辑,导入Selecotr模块
- from scrapy.selector import Selector
5.2 Selector(response=response).xpath()基本用法
- // #表示子子孙孙,即所有
- .// #当前对象的子孙中
- / #儿子
- /div #儿子中的div标签
- //div[@id] #所有标签含有id的div标签
- /div[@id='i1'] #儿子中的div且id ='i1'的标签
- obj.extract() #列表中每一个对象转换成字符串 ==>返回的是列表
- obj.extract_first() #列表中每一各对象转换成字符串==>返回的是列表中第一个元素
- //div/text() #获取所有div标签里的文本==》返回的是列表,元素是对象
- //a/@href #获取所有a标签里的url==》返回的是列表,元素是对象
- //a[starts-with(@href,"link")] #获取所有a标签,并且href属性是以link开头的
- //a[re:test(@href,"/sitehome/p/\d+")]/@href #正则,获取所有a标签属性href符合/sitehome/p/数字的
- //div[@id='i1'][@href=''xx] #[][]且的意思,即所有含有id='i1'且href='xxx'的div标签
- //a[contains(@href, "link")] #所有href字段包含link字符串的a标签
5.3 简单示例
需求:在www.ip138.com网站里,打印如下a标签的文本内容和url地址
在爬虫文件(baidu.py)里的parse类方法里编辑
- # -*- coding: utf-8 -*-
- import scrapy
- from scrapy.selector import Selector
- class BaiduSpider(scrapy.Spider):
- name = 'baidu'
- allowed_domains = ['ip138.com']
- start_urls = ['http://www.ip138.com/']
- def parse(self, response):
- #请求该页面下所有a标签==》列表,每个元素都是对象
- #找到div标签里有class=mod-guide属性下的所有子孙a标签里文本内容
- text_obj_list = Selector(response=response).xpath('//div[@class="module mod-guide"]//a/text()')
- # 找到div标签里有class=mod-guide属性下的所有子孙a标签里url
- url_obj_list = Selector(response=response).xpath('//div[@class="module mod-guide"]//a/@href')
- #将列表中对象转化成列表中字符串
- text_str_list = text_obj_list.extract()
- url_str_list = url_obj_list.extract()
- for a_text,a_url in zip(text_str_list,url_str_list):
- print(a_text,a_url)
代码
如何运行代码?
- 在cmd窗口,进入项目目录,运行scrapy crawl baidu
5.4 获取当前网页中的所有页码实例
需求:获取博客园里的首页页码url
在爬虫文件(ip138.py)里的parse类方法里编辑
- # -*- coding: utf-8 -*-
- import scrapy
- from scrapy.selector import Selector
- class Ip138Spider(scrapy.Spider):
- name = 'ip138'
- allowed_domains = ['www.cnblogs.com']
- start_urls = ['https://www.cnblogs.com/']
- urls_set = set()
- def parse(self, response):
- # text_obj_list = Selector(response=response).xpath('//div[@class="module mod-guide"]//a/text()')
- # url_obj_list = Selector(response=response).xpath('//div[@class="module mod-guide"]//a/@href')
- #
- # text_str_list = text_obj_list.extract()
- # url_str_list = url_obj_list.extract()
- #
- # for text,url in zip(text_str_list,url_str_list):
- # print(text,url)
- #获取当前页里的所有页码的url对象列表
- url_obj_list = Selector(response=response).xpath('//div[@class="pager"]/a/@href')
- ##或者2: starts-with(@属性,'值开头')
- #url_obj_list = Selector(response=response).xpath('//a[starts-with(@href,"/sitehome/p/")]/@href')
- ##或者3:正则表达式固定用法re:test(@属性值,"正则表达式")
- #url_obj_list = Selector(response=response).xpath('//a[re:test(@href,"/sitehome/p/\d+")]/@href')
- #将对象列表转换成字符串列表
- url_str_list = url_obj_list.extract()
- for url in url_str_list:
- print(url)
- #1.通过集合去除重复url
- #2.使用加密的MD5存储url,好处:加密和等长
- url_md5 = self.my_md5(url)
- if url_md5 not in self.urls_set:
- self.urls_set.add(url_md5)
- print(url_md5)
- else:
- print('%s已经存在'%url_md5)
- def my_md5(self,url):
- import hashlib
- obj = hashlib.md5()
- obj.update(bytes(url,encoding='utf-8'))
- return obj.hexdigest()
代码
5.5 获得当前网页里的页码自动请求爬取实例
需求:自动爬取博客园的所有页码(基于5.4案例的基础)
在爬虫文件(ip138.py)里的parse类方法里编辑
- # -*- coding: utf-8 -*-
- import scrapy
- from scrapy.selector import Selector
- from scrapy.http import Request
- class Ip138Spider(scrapy.Spider):
- name = 'ip138'
- allowed_domains = ['www.cnblogs.com']
- start_urls = ['https://www.cnblogs.com/']
- urls_set = set()
- def parse(self, response):
- #获取当前页里的所有页码的url对象列表
- url_obj_list = Selector(response=response).xpath('//div[@class="pager"]/a/@href')
- ##或者2: starts-with(@属性,'值开头')
- #url_obj_list = Selector(response=response).xpath('//a[starts-with(@href,"/sitehome/p/")]/@href')
- ##或者3:正则表达式固定用法re:test(@属性值,"正则表达式")
- #url_obj_list = Selector(response=response).xpath('//a[re:test(@href,"/sitehome/p/\d+")]/@href')
- #将对象列表转换成字符串列表
- url_str_list = url_obj_list.extract()
- for url in url_str_list:
- #1.通过集合去除重复url
- if url not in self.urls_set:
- #print(url)
- self.urls_set.add(url)
- #拼接完整的url地址
- full_url = self.start_urls[0] + url
- #将url页码传给调度器去请求,并将下载的结果交给parse方法,yield的作用是将请求放入调度器
- yield Request(url=full_url,callback=self.parse)
- for url in self.urls_set:
- print(url)
代码
在setting.py中结尾新增一行DEPTH_LIMIT=1来指定递归的层次,默认是0,所有层次
实例中关键点概括
- @href #取属性值
- starts-with(@href,"xx") #属性href的值以xx开始
- re:test(@href,"/sitehome/p/\d+") #正则re:test固定搭配
- yield Request(url=full_url,callback=self.parse) #交给调度器
六、item,pipeline使用
6.1 需求:将博客园的文章标题和url保存到一个文件a.txt文件里。
各文件代码如下:
- # -*- coding: utf-8 -*-
- import scrapy
- from scrapy.selector import Selector
- from scrapy.http import Request
- from .. import items
- class Ip138Spider(scrapy.Spider):
- name = 'ip138'
- allowed_domains = ['www.cnblogs.com']
- start_urls = ['https://www.cnblogs.com/']
- urls_set = set()
- def parse(self, response):
- #获取当前页面里的标题和url==>返回字符串
- title_str_list = Selector(response=response).xpath('//a[@class="titlelnk"]/text()').extract()
- href_str_list = Selector(response=response).xpath('//a[@class="titlelnk"]/@href').extract()
- for title_str,href_str in zip(title_str_list,href_str_list):
- #print(title_str,' ',href_str)
- #此处的参数title,和href来自于items.py文件里类Cnblogs里的属性
- item_obj = items.Cnblogs(title=title_str,href=href_str)
- #将item对象传递给pipelines
- yield item_obj
- #获取当前页里的所有页码的url对象列表
- page_obj_list = Selector(response=response).xpath('//div[@class="pager"]/a/@href')
- ##或者2: starts-with(@属性,'值开头')
- #page_obj_list = Selector(response=response).xpath('//a[starts-with(@href,"/sitehome/p/")]/@href')
- ##或者3:正则表达式固定用法re:test(@属性值,"正则表达式")
- #page_obj_list = Selector(response=response).xpath('//a[re:test(@href,"/sitehome/p/\d+")]/@href')
- #将对象列表转换成字符串列表
- page_str_list = page_obj_list.extract()
- for url in page_str_list:
- #1.通过集合去除重复url
- if url not in self.urls_set:
- self.urls_set.add(url)
- print(url)
- #拼接完整的url地址
- full_url = self.start_urls[0] + url
- #将url页码传给调度器去请求,并将下载的结果交给parse方法,yield的作用是将请求放入调度器
- yield Request(url=full_url,callback=self.parse)
ip138.py文件
- # -*- 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
- class Cnblogs(scrapy.Item):
- # define the fields for your item here like:
- # name = scrapy.Field()
- title = scrapy.Field()
- href = scrapy.Field()
items.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
- class Day0310Pipeline(object):
- def process_item(self, item, spider):
- content = "%s %s\n"%(item['title'],item['href'])
- f = open('a.json','a')
- f.write(content)
- f.close()
- # return item
pipelines.py文件
- ITEM_PIPELINES = {
- 'day0310.pipelines.Day0310Pipeline': 300,
- }
setting.py文件
6.2 实例中关键点概括
- #items.py文件中
- class Cnblogs(scrapy.Item):
- title = scrapy.Field()
- href = scrapy.Field()
- #ip138.py文件中
- from .. import items
- item_obj = items.Cnblogs(title=title_str,href=href_str) #此处的参数title,和href来自于items.py文件里类Cnblogs里的属性
- yield item_obj #将item对象传递给pipelines
- #pipelines.py文件中,可对收集到的数据进行存储
- class Day0310Pipeline(object):
- def process_item(self, item, spider): #item为ip138.py文件里的对象化的数据,spider为来自哪只蜘蛛对象
- content = "%s %s\n"%(item['title'],item['href'])
- f = open('a.json','a')
- f.write(content)
- f.close()
- #setting.py文件中注册下pipelines的类
- ITEM_PIPELINES = {
- 'day0310.pipelines.Day0310Pipeline': 300,
- }
- 数字越高越优先
Scrapy爬虫框架学习的更多相关文章
- scrapy爬虫框架学习笔记(一)
scrapy爬虫框架学习笔记(一) 1.安装scrapy pip install scrapy 2.新建工程: (1)打开命令行模式 (2)进入要新建工程的目录 (3)运行命令: scrapy sta ...
- Scrapy 爬虫框架学习笔记(未完,持续更新)
Scrapy 爬虫框架 Scrapy 是一个用 Python 写的 Crawler Framework .它使用 Twisted 这个异步网络库来处理网络通信. Scrapy 框架的主要架构 根据它官 ...
- Python之Scrapy爬虫框架安装及简单使用
题记:早已听闻python爬虫框架的大名.近些天学习了下其中的Scrapy爬虫框架,将自己理解的跟大家分享.有表述不当之处,望大神们斧正. 一.初窥Scrapy Scrapy是一个为了爬取网站数据,提 ...
- scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250
scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250 前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大 ...
- Scrapy爬虫框架(实战篇)【Scrapy框架对接Splash抓取javaScript动态渲染页面】
(1).前言 动态页面:HTML文档中的部分是由客户端运行JS脚本生成的,即服务器生成部分HTML文档内容,其余的再由客户端生成 静态页面:整个HTML文档是在服务器端生成的,即服务器生成好了,再发送 ...
- Scrapy爬虫框架中的两个流程
下面对比了Scrapy爬虫框架中的两个流程—— ① Scrapy框架的基本运作流程:② Spider或其子类的几个方法的执行流程. 这两个流程是互相联系的,可对比学习. 1 ● Scrapy框架的基本 ...
- 安装scrapy 爬虫框架
安装scrapy 爬虫框架 个人根据学习需要,在Windows搭建scrapy爬虫框架,搭建过程种遇到个别问题,共享出来作为记录. 1.安装python 2.7 1.1下载 下载地址 1.2配置环境变 ...
- scrapy爬虫框架教程(二)-- 爬取豆瓣电影
前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大家讲解一个完整爬虫的流程. 工具和环境 语言:python 2 ...
- Python爬虫教程-31-创建 Scrapy 爬虫框架项目
本篇是介绍在 Anaconda 环境下,创建 Scrapy 爬虫框架项目的步骤,且介绍比较详细 Python爬虫教程-31-创建 Scrapy 爬虫框架项目 首先说一下,本篇是在 Anaconda 环 ...
随机推荐
- MyBatis从入门到精通:第二章数据的创建与插入文件
数据库表的创建: create table sys_user ( id bigint not null auto_increment, ), user_password ), user_email ) ...
- I/O:RandomAccessFile
RandomAccessFile: /* 此类的实例支持对随机访问文件的读取和写入.随机访问文件的行为类似存储在文件系统中的一个 大型 byte 数组.存在指向该隐含数组的光标或索引,称为文件指针:输 ...
- 看MySQL的参数调优及数据库锁实践有这一篇足够了
史上最强MySQL参数调优及数据库锁实践 1. 应用优化 1.2 减少对MySQL的访问 1.2.1 避免对数据进行重复检索 1.2.2 增加cache层 1.3 负载均衡 1.3.1 利用MySQL ...
- LiteIDE TARGETARGS -conf_path=E:/PokerServer/src/GameServer/conf/texas.xml -log_dir=E:/PokerServer/src/GameServer/main/log
LiteIDE TARGETARGS -conf_path=E:/PokerServer/src/GameServer/conf/texas.xml -log_dir=E:/PokerServer/s ...
- 个人永久性免费-Excel催化剂功能第42波-任意字符指定长度随机函数
日常做表过程中,难免会有一些构造数据的场景,构造数据最好是用随机的数据,如随机密码,随机英文字母.数字等.在Excel原生的随机函数Rand中,仅能处理数字的随机,且最终生成的结果也是数字类型.今天E ...
- 集群之间配置 SSH无密码登录
集群之间配置 SSH无密码登录 配置 ssh (1)基本语法 ssh 另一台电脑的 ip 地址 (2)ssh 连接时出现 Host key verification failed 的解决方法 # ss ...
- [剑指offer] 3. 从头到尾打印链表
题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 思路: 利用容器,遍历一遍加入到一个新容器里,然后反置输出. vector 用 reverse stack 则直接一个个出栈 ...
- Java EE.Servlet.处理请求
Servlet的核心工作便是处理客户端提交的请求信息,生成动态响应信息返回客户端. 1.请求参数 POST方法一般用于更新服务器上的资源,当时用POST方法时,提交的数据包含在HTTP实体内,而GET ...
- laravel5.6 使用迁移创建表
laravel 使用迁移创建表 创建迁移文件 --table 和 --create 选项可以用于指定表名以及该迁移是否要创建一个新的数据表.这些选项只需要简单放在上述迁移命令后面并指定表名: php ...
- 计时器(Chronometer)、标签(TabHost)
计时器(Chronometer) 方法 描述 public Chronometer(Context context)[构造方法] 创建Chronometer对象 public long getBase ...