中山网站建设文化渠道,一般的学校网站怎么做,西安网页开发,如何查网站外链文章目录#xff11;python基础1.1 列表生成式和生成器的区别 #xff1f;1.2 如何不用任何循环快速筛掉列表中的奇数元素 #xff1f;1.3 map和reduce的用法1.4 装饰器的作用1.5 Python中__new__与__init方法的区别1.6 python中的设计模式1.7 lambda函数#xff0c;以及它…
文章目录python基础1.1 列表生成式和生成器的区别 1.2 如何不用任何循环快速筛掉列表中的奇数元素 1.3 map和reduce的用法1.4 装饰器的作用1.5 Python中__new__与__init方法的区别1.6 python中的设计模式1.7 lambda函数以及它有什么好处2 反爬问题2.1 如何处理封IP的反爬2.2 如何处理验证码2.3 代理问题2.4 验证码处理2.5 模拟登陆问题3 数据库问题3.1 说几个redis中的数据类型和命令3.2 MySQL中的inner join和left join的区别 4 爬虫问题4.1 常用的网络数据爬取方法4.2 设计一个基于session登录验证的爬虫方案5 框架问题5.1 scrapy的基本结构五个部分都是什么请求发出去的整个流程5.2 scrapy的去重原理 指纹去重到底是什么原理5.4 scrapy中间件有几类分别在哪里起的作用面向切面编程6 分布式6.1 分布式原理6.2 分布式如何判断爬虫已经停止了6.3 分布式去重原理6.4 分布式爬虫的实现例子1例子27 模拟登录7.1 selenium模拟登录遇到验证码7.2 tesseract-OCR的在验证码识别中的重训练与使用7.3 搭建IP代理池python基础
1.1 列表生成式和生成器的区别
列表生成式和生成器都可以来生成一个列表。列表生成式生成的列表所有元素对象被立即创建在内存中当元素过多时势必会占用过多内存要用到生成器它即时创建一个生成器对象未创建任何元素。生成器来生成一个列表它不会立即创建大量的对象在内存中。生成器的缺点没有列表的方法如append、len、index等等通过next方法来访问其元素可通过循环打印出所有的元素
1.2 如何不用任何循环快速筛掉列表中的奇数元素
用内置函数filter配合匿名函数过滤掉数组中不符合条件的元素
print (filter(lambda x:x%2 0, [1,2,3,4,5]))
#[2,4]1.3 map和reduce的用法
map map()函数接收两个参数一个是函数一个是Iterable。
例子1 def f(x): return x * x r map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) print(list®) # [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce
reduce把一个函数作用在一个序列[x1, x2, x3, …]上这个函数必须接收两个参数reduce把结果继续和序列的下一个元素做累积计算其效果就是
reduce(f, [x1, x2, x3, x4]) f(f(f(x1, x2), x3), x4)例子1
from functools import reduce
def add(x, y):return x y
print(reduce(add, [1, 3, 5, 7, 9]))
#251.4 装饰器的作用
装饰器本质上是一个Python函数它可以让其他函数在不需要做任何代码变动的前提下增加额外功能提高了代码的复用性。比如在函数调用前后自动打印日志但又不希望修改now()函数的定义这种在代码运行期间动态增加功能的方式称之为“装饰器”Decorator。
1.5 Python中__new__与__init方法的区别
_new_:它是创建对象时调用会返回当前对象的一个实例可以用_new_来实现单例
_init_:它是创建对象后调用对当前对象的一些实例初始化无返回值。
1.6 python中的设计模式
1.7 lambda函数以及它有什么好处
lambda 表达式通常是在需要一个函数但是又不想费神去命名一个函数的场合下使用也就是指匿名函数 lambda函数首要用途是指点短小的回调函数
lambda [arguments]:expressionalambdax,y:xya(3,11)2 反爬问题
2.1 如何处理封IP的反爬
因为网络上的免费代理平台可用的IP数量太少所以自己写一个模块去抓取平台的IP来维护是没有什么意义的。我选择的是付费代理通过使用平台的api在本地动态维护一个IP缓存池来供给分布式架构的爬虫节点使用。这个缓存池不需要做IP有效性验证因为我的爬虫若下载某个Request彻底失败后会把这个Request重新放回Request队列而且选择一个好的代理平台可以大大提高代理IP质量。我常用的是快代理。缓存池的IP被取走一个池中的数量就减少一个当数量少于M时再从平台获取N个。
2.2 如何处理验证码
答简单的验证码可以通过预处理灰度、二值化、去除干燥点验证码图片再使用tesseract库来识别 复杂一点的则接入付费平台识别。当然如果这个目标网站的app端没有验证码的话会优先通过app端爬取。
2.3 代理问题
1为什么会用到代理 2代理怎么使用具体代码请求在什么时候添加的代理 3代理失效了怎么处理
2.4 验证码处理
1登陆验证码处理 使用tesseract来识别不过tesseract你要自行去训练它不然识别率出奇的低。
2爬取速度过快出现的验证码处理 3如何用机器识别验证码
2.5 模拟登陆问题
1模拟登陆流程 2cookie如何处理 3如何处理网站传参加密的情况
3 数据库问题
3.1 说几个redis中的数据类型和命令
3.2 MySQL中的inner join和left join的区别
INNER JOIN内连接,或等值连接取得两个表中存在连接匹配关系的记录。 LEFT JOIN左连接取得左表table1完全记录即使右表table2并无对应匹配记录。
扩展RIGHT JOIN右连接与 LEFT JOIN 相反取得右表table2完全记录即使左表table1并无匹配对应记录。
4 爬虫问题
4.1 常用的网络数据爬取方法
正则表达式Beautiful Soup, lxml
4.2 设计一个基于session登录验证的爬虫方案
5 框架问题
5.1 scrapy的基本结构五个部分都是什么请求发出去的整个流程
5.2 scrapy的去重原理 指纹去重到底是什么原理
1scrapy本身自带有一个中间件 2scrapy源码中可以找到一个dupefilters.py去重器 3需要将dont_filter设置为False开启去重默认是True没有开启去重 4 对于每一个url的请求调度器都会根据请求得相关信息加密得到一个指纹信息并且将指纹信息和set()集合中的指纹信息进行比对如果set()集合中已经存在这个数据就不在将这个Request放入队列中 5如果set()集合中没有存在这个加密后的数据就将这个Request对象放入队列中等待被调度
5.4 scrapy中间件有几类分别在哪里起的作用面向切面编程
1、scrapy的中间件理论上有三种(Schduler Middleware,Spider Middleware,Downloader Middleware),在应用上一般有以下两种
1.爬虫中间件Spider Middleware 主要功能是在爬虫运行过程中进行一些处理.
2.下载器中间件Downloader Middleware 主要功能在请求到网页后,页面被下载时进行一些处理.
2、使用 1.Spider Middleware有以下几个函数被管理:- process_spider_input 接收一个response对象并处理,位置是Downloader--process_spider_input--Spiders(Downloader和Spiders是scrapy官方结构图中的组件)- process_spider_exception spider出现的异常时被调用- process_spider_output 当Spider处理response返回result时,该方法被调用- process_start_requests 当spider发出请求时,被调用位置是Spiders–process_start_requests–Scrapy Engine(Scrapy Engine是scrapy官方结构图中的组件)
2.Downloader Middleware有以下几个函数被管理
- process_request request通过下载中间件时该方法被调用
- process_response 下载结果经过中间件时被此方法处理
- process_exception 下载过程中出现异常时被调用 编写中间件时,需要思考要实现的功能最适合在那个过程处理,就编写哪个方法.中间件可以用来处理请求,处理结果或者结合信号协调一些方法的使用等.也可以在原有的爬虫上添加适应项目的其他功能,这一点在扩展中编写也可以达到目的,实际上扩展更加去耦合化,推荐使用扩展.6 分布式
6.1 分布式原理
这里重要的就是我的队列通过什么维护 这里一般我们通过Redis为维护Redis非关系型数据库Key-Value形式存储结构灵活。 并且redis是内存中的数据结构存储系统处理速度快提供队列集合等多种存储结构方便队列维护
如何去重 这里借助redis的集合redis提供集合数据结构在redis集合中存储每个request的指纹 在向request队列中加入Request前先验证这个Request的指纹是否已经加入集合中。如果已经存在则不添加到request队列中如果不存在则将request加入到队列并将指纹加入集合
如何防止中断如果某个slave因为特殊原因宕机如何解决 这里是做了启动判断在每台slave的Scrapy启动的时候都会判断当前redis request队列是否为空 如果不为空则从队列中获取下一个request执行爬取。如果为空则重新开始爬取第一台丛集执行爬取向队列中添加request
如何实现上述这种架构 这里有一个scrapy-redis的库为我们提供了上述的这些功能 scrapy-redis改写了Scrapy的调度器队列等组件利用他可以方便的实现Scrapy分布式架构
6.2 分布式如何判断爬虫已经停止了
查一下爬虫的状态
spider.getStatus();//获取爬虫状态
6.3 分布式去重原理
6.4 分布式爬虫的实现
例子1 (1).使用两台机器一台是win10一台是ubuntu16.04分别在两台机器上部署scrapy来进行分布式抓取一个网站. (2).ubuntu16.04的ip地址为39.106.155.194用来作为redis的master端win10的机器作为slave. (3).master的爬虫运行时会把提取到的url封装成request放到redis中的数据库“dmoz:requests”并且从该数据库中提取request后下载网页再把网页的内容存放到redis的另一个数据库中“dmoz:items”. (4).slave从master的redis中取出待抓取的request下载完网页之后就把网页的内容发送回master的redis. (5).重复上面的3和4直到master的redis中的“dmoz:requests”数据库为空再把master的redis中的“dmoz:items”数据库写入到mongodb中. (6).master里的reids还有一个数据“dmoz:dupefilter”是用来存储抓取过的url的指纹使用哈希函数将url运算后的结果是防止重复抓取的.
例子2
参考https://juejin.im/post/5b0ba020f265da09151f56c7#heading-12
7 模拟登录
7.1 selenium模拟登录遇到验证码
截图找到验证码的位置进行识别
#因为验证码不能一次就正确识别我加了循环一直识别直到登录成功 while True: #清空验证码输入框因为可能已经识别过一次了里面有之前识别的错的验证码 driver.find_element_by_name(“verificationCode”).clear() # 截图或验证码图片保存地址 screenImg “H:\screenImg.png” # 浏览器页面截屏 driver.get_screenshot_as_file(screenImg) # 定位验证码位置及大小 location driver.find_element_by_name(‘authImage’).location size driver.find_element_by_name(‘authImage’).size #下面四行我都在后面加了数字理论上是不用加的但是不加我这截的不是验证码那一块的图可以看保存的截图根据截图修改截图位置 left location[‘x’]530 top location[‘y’]175 right location[‘x’] size[‘width’]553 bottom location[‘y’] size[‘height’]200 # 从文件读取截图截取验证码位置再次保存 img Image.open(screenImg).crop((left, top, right, bottom)) #下面对图片做了一些处理能更好识别一些相关处理再百度看吧 img img.convert(‘RGBA’) # 转换模式L | RGB img img.convert(‘L’) # 转换模式L | RGB img ImageEnhance.Contrast(img) # 增强对比度 img img.enhance(2.0) # 增加饱和度 img.save(screenImg) # 再次读取识别验证码 img Image.open(screenImg) code pytesseract.image_to_string(img) #打印识别的验证码 #print(code.strip())
7.2 tesseract-OCR的在验证码识别中的重训练与使用
参考 https://zhuanlan.zhihu.com/p/40178190
7.3 搭建IP代理池