python爬虫面试遇到的问题

文章目录

    • 1python基础
      • 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
        • 例子2
    • 7 模拟登录
      • 7.1 selenium模拟登录,遇到验证码:
      • 7.2 tesseract-OCR的在验证码识别中的重训练与使用
      • 7.3 搭建IP代理池

1python基础

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]))
#25

1.4 装饰器的作用

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,提高了代码的复用性。比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

1.5 Python中__new__与__init方法的区别

_new_:它是创建对象时调用,会返回当前对象的一个实例,可以用_new_来实现单例

_init_:它是创建对象后调用,对当前对象的一些实例初始化,无返回值。

1.6 python中的设计模式

1.7 lambda函数,以及它有什么好处

lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数
lambda函数:首要用途是指点短小的回调函数

lambda [arguments]:expression
>>> a=lambdax,y:x+y
>>> a(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)模拟登陆流程
(2)cookie如何处理
(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的去重原理 (指纹去重到底是什么原理)

(1)scrapy本身自带有一个中间件
(2)scrapy源码中可以找到一个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代理池

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/273805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu18 常用命令

文章目录卸载和安装卸载和安装 1.打开一个终端,输入dpkg --list ,按下Enter键,终端输出以下内容,显示的是你电脑上安装的所有软件。 2.安装 dpkg –i name.deb 安装一个 deb 包;在终端上输入命令sudo apt-get --purge remove 包…

以嵌入式系统设计师考试成绩,开始嵌入式博客之旅

http://www.rkb.gov.cn/jsj/cms/s_contents/download/s_dt201003110106.html 转载于:https://www.cnblogs.com/yueqian-scut/p/3952268.html

SSH框架配置及Maven使用

1.SSH框架配置 1.1. SSH框架介绍 1.2. SSH框架配置 所需资源下载: l jdk; 从Oracle官方网站:http://www.oracle.com/technetwork/cn/java/javase/downloads/index.html下载jdk,win7是默认安装在C:\Program Files (x86)\Java\jdk1.6.0_25路径下…

cookie,session的区别和联系(补充token)

文章目录1 http为什么是无状态的2 cookie 和session 的区别详解3 token参考:备注: 博客文章仅限于学习,禁止商用1 http为什么是无状态的 2 cookie 和session 的区别详解 这些都是基础知识,不过有必要做深入了解。先简单介绍一下。 二者的定…

库函数和系统调用的区别

前言 这是一对非常容易混淆的概念。对于用户( 应用程序开发者 )来说,并不一定要严格区分其意义。因为在用户看来,它们都是以C函数的形式出现的。但了解二者的区别对我们掌握整个计算机系统有很大帮助。 区别 1. 一部分库函数实现需要使用系统调用( 如 pr…

Flask 从入门到熟悉(不敢称为精通)

文章目录2.1 Flask介绍及其安装2.2 Virtualenv3.1 一个最小的应用3.2 外部课件服务器3.3 调试模式4.1 路由介绍4.2 变量规则4.3 构建URL4.4 HTTP 方法4 总结5.1 静态文件5.2 渲染模板5.3 练习66.1 接收请求数据6.2 请求对象6.3 文件上传6.4 Cookies6 总结77.1 重定向和错误7.2 …

Ext JS 5 beta版发布

原文:Announcing Public Beta of Ext JS 5我们非常高兴的宣布,Sencha Ext JS 5 beta版本开始进行公测了。这个beta版本可以让你、我们Sencha社区来对我们的Ext JS 5的工作进度进行评测。对于所以Ext JS开发人员,这事一个很好的机会来协助完成…

算法【二分查找】(数组)

1 .山脉数组的巅峰索引 信息 我们把符合下列属性的数组 A 称作山脉&#xff1a; A.length > 3 存在 0 < i < A.length - 1 使得A[0] < A[1] < … A[i-1] < A[i] > A[i1] > … > A[A.length - 1] 给定一个确定为山脉的数组&#xff0c;返回任何满…

关于癌症的十大谣言

最近&#xff0c;国外网站总结了西方社会中流行的十个关于癌症的谣言&#xff0c;其中很多谣言在我们周围也有广泛的传播。 谣言1&#xff1a;癌症是人为导致的现代疾病 或许在公众的认知里&#xff0c;癌症在今天要比历史上任何时期都重要。不过实际上&#xff0c;癌症可不是一…

[python 进阶] 第7章 函数装饰器和闭包

文章目录7.1 装饰器基础知识7.2 Python何时执行装饰器7.3 使用装饰器改进“策略”7.4 变量作用域(global)备注 -比较字节码&#xff08;暂略&#xff09;7.5 闭包7.6 nonlocal声明global和nonlocal的区别7.7 实现一个简单的装饰器7.8 标准库中的装饰器7.8.1 使用functools.lru_…

自制“低奢内”CSS3登入表单,包含JS验证,请别嫌弃哦。

要求 必备知识 基本了解CSS语法,初步了解CSS3语法知识。和JS/JQuery基本语法。 开发环境 Adobe Dreamweaver CS6 演示地址 演示地址 预览截图(抬抬你的鼠标就可以看到演示地址哦): 制作步骤: 一, html结构 <div id"home"><form id"login" class…

class里面只能写以下5种

转载于:https://www.cnblogs.com/phplearnings/p/3650849.html

【排序】算法(python实现)

文章目录python 排序算法1 插入排序1.1 直接插入排序算法思想1.2 希尔排序算法思想2. 选择排序2.1 简单选择排序2.2 堆排序参考python 排序算法 1 插入排序 1.1 直接插入排序 算法思想 直接插入排序的核心思想就是&#xff1a;将数组中的所有元素依次跟前面已经排好的元素相…

OpenSSL漏洞补救办法详解(转)

CVE-2014-0160漏洞背景 2014年4月7日OpenSSL发布了安全公告&#xff0c;在OpenSSL1.0.1版本中存在严重漏洞(CVE-2014-0160)。OpenSSL Heartbleed模块存在一个BUG&#xff0c;问题存在于ssl/dl_both.c文件中的心跳部分&#xff0c;当攻击者构造一个特殊的数据包&#xff0c;满足…

SharePoint 自定义WebPart之间的连接

1、创建SharePoint解决方案&#xff0c;添加两个WebPart分别用来发送和接收&#xff1b; 2、发送值的WebPart需要继承自IWebPartField(当然&#xff0c;根据需要还可以选择IWebPartField,IWebPartParameters,IWebPartRow,IWebPartTable&#xff0c;具体参见msdn)&#xff0c;原…

[python 进阶] 9. 符合Python风格的对象

文章目录9.1 对象表示形式9.2 再谈向量类9.3 备选构造方法9.4 classmethod与staticmethod9.5 格式化显示9.6 可散列的Vector2d什么是可散列的数据类型9.6 可散列的Vector9.7 Python的私有属性和“受保护的”属性9.8 使用 __slots__ 类属性节省空间本章包含以下话题&#xff1a;…

android软件获取系统签名

有时候有的功能必须要有系统签名才能使用&#xff0c;例如调用系统自带的Surface.screenShot方法时&#xff0c;就必须在androidManifest.xml里声明android:sharedUserId"android.uid.system" 但是这个时候在编译生成的apk很有可能无法安装的情况 并且报这个错误&…

Python3中的可变与不可变类型

在描述变量是否是可变类型时&#xff0c;可变与否实际上说的是对变量进行“修改”时变量的内存地址是否会发生变化&#xff0c;而非值是否可变。在Python中&#xff0c;对不可变的变量进行“修改”实际上是重新赋值&#xff0c;对可变的变量进行修改才是真正的修改&#xff0c;…

python中带*(单星号)的变量和**(双星号)的变量

一、*args的使用方法 *args 用来将参数打包成tuple给函数体调用二、**kwargs的使用方法 **kwargs 打包关键字参数成dict给函数体调用注意点&#xff1a;参数arg、*args、**kwargs三个参数的位置必须是一定的。必须是(arg,*args,**kwargs)这个顺序&#xff0c;否则程序会报错。单…