本文由excel直接复制而来,可能会导致格式问题。敬请谅解
Python框架Scrapy学习
Python, Scrapyt, PyCharm
基于Scrapy搭建分布式爬虫,打造搜索引擎
前言
通过elasticsearch和django搭建搜索引擎网站
scrapy是异步io框架,没有多线程
注:文章中所有pc均为PyCharm
学习流程
- 环境配置和基础知识铺垫
- 爬取真实数据
- scrapy突破反爬虫技术
- scrapy进阶
- scrapy redis 分布式爬虫
- elasticsearch和django实现搜索引擎
pyCharm安装
pip安装
下载pip解压,解压目录下cmd 使用python setup.py install安装pip 配置环境变量
第一个是python环境变量,第二个是pip环境变量
virtualenv(虚拟环境)
可以随意切换虚拟环境python版本
安装
pip install virtualenv
新建
virtualenv [Name] 新建到当前目录下
进入虚拟环境
进入虚拟环境目录scripts文件夹下运行activate.bat文件
退出虚拟环境
运行deactivate.bat
切换python版本
virtualenv -p [PythonVersion][1]
[Name] 新建到当前目录下
安装virtualenv管理工具virtualenvwrapper
命令
- workon 查看所有虚拟环境
- mkvirtualenv [Name] 安装后会自动进入虚拟环境
安装
pip install virtualenvwrapper
pip install virtualenvwrapper-win
安装成功后配置环境变量设置wrapper的指定存储地址
之前的虚拟环境可以直接copy过来使用
python版本各种安装包
爬虫能做什么
正则表达式
- ^标识以什么开头 eg::^b 必须以b开头得字符串
- .标识任意字符
- $标识以什么结尾 eg:3$ 比许以3结尾得字符串
- ?标识非贪婪匹配模式[2]
- +标识前面字符出现至少一次
- {2}标识前面紧跟字符出现2次
- {2,}标识前面紧跟字符至少出现2此
- {2,5}标识前面紧跟字符出现大于2次小于5次
- |标识或
- []标识只要满足中括号中任意一个,也可[0-9]标识一个区间,[^1]标识不等于什么,
- \s标识空格
- \S标识只要不是空格都可以
- \w标识[A-Za-z0-9_][3]
这些 - \W标识只要不是[A-Za-z0-9_]这些都可以
- [\u4E00-\u9FA5]固定写法,标识汉字
- \d标识数字
如果多个匹配一个包含-得时候一定不要写中间。会提示错误,因为他认为你是在查什么-什么
深度优先和广度优先
网站的树结构
深度优先和广度优先算法
深度优先顺序
A-B-D-E-I-C-F-G-H(递归算法实现)
广度优先
A-B-C-D-E-F-G-H-I(队列算法实现)
爬虫URL去重策略
- 将访问过的URL保存到数据库(最垃圾)
- 将访问过的URL保存到set中(内存占用到爆炸)[4]
- URL经过md5等方法哈希后保存到set中(进行几倍压压缩,还凑活)scrapy中的URL去重就是类似使用了这种方法
- 使用batmap方法,将访问过的URL通过hash函数映射到某一位(更进一步压缩内存,但是哈希冲突非常高。容易把不同URl映射到同一位)[5]
- bloomfilter方法对bitmap进行改进,多重hash函数降低冲突
字符串编码
计算机只能处理数字,所有文本都需要转换成数字才能进行处理,计算机中8个bit作为一个字节,所以一个字节能标识最大的数字就是255.所以ASCII编码足够用了
ASCII处理中文明显不够用,所以中国制定GB2312编码,用两个字节标识一个汉字,所以标准就越来越多。所以unicode就出现了。会统一到一套编码中
区别
unicode:虽然占用空间但是做编程的时候会比utf-8简单
utf-8:如果做文件保存或者网络传输就会优势明显
python中字符转换
python2中
encode时一定要保证前面字符时unicode编码
decode一定是转换成unicode编码同时给出原字符编码格式
python3中
已经把所有编码全部堪称unicode了。所以不需要decode了。直接转utf-8就可以了(encode)这也是2-3最大的区别
Scrapy安装和使用
进入虚拟环境
pip install Scrapy
https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
如果提示错误要从上面网址手动下载中间件之后在进行安装Scrapy
Scrapy核心Twisted 事件循环+回调模式
创建第一个程序蜘蛛(Spider)
cmd进入安装scrapy的虚拟环境。
创建一个项目[6]
:
scrapy startproject Article
进入pc[7]
打开项目观察项目结构
如果想快速创建你的第一个spider会有很人性化的提示
cmd执行创建我的第一个spider
scrapy genspider jobbole news.cnblogs.com
之后在pc里面看
没有找到包?这时我们应该配置一下解释器(Project Interpreter)找到之前虚拟环境下script下的python.exe来指定虚拟环境,如下图
需求分析
这里主要是分特定页面。制定抓取方法
第一次使用scrapy
启动一个spider :
spider crawl [name] #name在下图
如果想在pc中使用debug
则需要新建一个main.py然后使用pc来代替执行当前命令
需要引用
from scrapy.cmdline import execute
获取项目根目录[8]
os.path.dirname(os.path.abspath(__file__))
将一个目录放到python的搜索目录当中
sys.path.append()
执行命令(因为要debug,所以此命令相当于代替cmd命令)
execute(["scrapy","crawl","jobbole"])
然后在main函数下debug
然后看一下parse里面的response
xpath解析方法
xpath简介
XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。
XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初XPath的提出的初衷是将其作为一个通用的、介于XPointer与XSL间的语法模型。但是XPath很快的被开发者采用来当作小型查询语言。
- xpath使用路径表达式在xml和html中进行导航
- xpath包含标准函数库
- xpath是一个w3c的标准,是脱离语言存在的
xpath节点关系
- 父节点
- 子节点
- 同袍节点
- 先辈节点
- 后代节点
xpath语法[9]
xpath使用
浏览器中会给我们提供元素xpath
提取url(此方法太过依赖于id所以并不适用)
图中extract为获取全部,extract_first为获取第一个
下面进行优化
在scrapy分两次取元素时,第二次路径一定要使用 .
例如下图。取当前节点下所有的img元素,就要使用.//
例如下图。取当前节点下img元素,就要使用./
CSS选择器(学过前端的或者干前端得可以学,没有xpath强大)
CSS选择器语法
CSS选择器使用
response.css('CSS语法').extract()
如何不使用scrapy框架单独使用选择器
需要引用
from scrapy import Selector
然后如下图把html源代码赋给Selector的text中,就可以使用选择器了
编写我的第一个spider
parse方法
一般来说parse方法都是用来做抓取策略的而不是用来解析的。要有单独的方法来进行解析
一旦使用了yield,会直接把url请求会立马交给scrapy进行下载
可以使用meta传递参数
callback指request之后要执行什么
注:如果写parse_detail()则callback赋值的就是这个方法的返回值了。就不是把方法赋给callback了
yield(python关键词,生成器使用)
特性
- 可以停止得函数
如果出现yield则此函数就变成了特殊的函数。整个函数得返回值就变成了generator对象。如需读取应使用循环或者next迭代。截图如下
定义对象之后
没定义
yield只可以yield request 和 yield item 不可以是其他的
如果是request这里默认会走scrapy的下载逻辑
如果是item这里默认会走piplines[10]
,这里如何处理是自己定义好的
scrapy shell使用(在调试时不用每次请求,主要测试使用)
进入虚拟环境
scrapy shell 路径
items的定义和使用
使用时记录
查不出内容怎么办
原因:这里查询得只是服务器返回得原始html(右键查看源代码),并不会查询js执行过后得html
解决:
有可能此值被写到当前html文件得其他部分
寻找请求的接口。进行数据解析[11]
这里尽量不要使用同步的方法来执行,所以应该使用yield,当然对于少量数据。直接同步调用也是没有问题的
if __name__ == "__main__"什么作用
通俗的理解if __name__ == "__main__":假如你叫小明.py,在朋友眼中,你是小明(__name__== '小明');在你自己眼中,你是你自己(if __name__ == "__main__")。
if __name__ == "__main__"的意思是:当.py文件被直接运行时,if __name__ == "__main__"之下的代码块将被运行;当.py文件以模块形式被导入时,if __name__ == "__main__"之下的代码块不被运行。
---------------------------------------------以下是注释--------------------------------------------
- 填写python不同版本的文件路径。如:C:\Users\Lenovo\AppData\Local\Programs\Python\Python38-32\python.exe ↩
- 贪婪匹配是一直从左向右匹配到最后一个满足条件的字符串 ↩
- 大写字母小写字符数字和下划线 ↩
- 假定1E个url,1000000002byte50字符/1024/1024/1024 = 9G ↩
- 假定1E个url,100000000bit/8bypt/1024kb/1024m = 12m ↩
- 默认创建在当前目录 ↩
- PyCharm ↩
- 需要引用sys和os ↩
- https://www.cnblogs.com/cxd4321/archive/2007/09/24/903917.html ↩
- 默认scrapy会创建好piplines.py文件 ↩
- 需要引用requests包 ↩
完全个人研究,有错希望大神纠正。也可留下您的联系方式,共同探讨
——————————————————————————————————
作者:Henny_CHN
转载请标明出处,原文地址: