1.你写爬虫的时候都遇到过什么?反爬虫措施,你是怎么解决的?
- 通过headers反爬虫;
- 基于用户行为的发爬虫:(同一IP短时间内访问的频率);
- 动态网页反爬虫(通过ajax请求数据,或者通过JavaScript生成);
解决途径:
- 对于基本网页的抓取可以自定义headers,将header随request一起发送(一般是User-Agent,Cookie)
- 使用IP代理池爬取或者降低抓取频率
- 使用selenium + phantomjs 进行抓取抓取动态数据,或者找到动态数据加载的json页面
2.用的什么框架,为什么选择这个框架?
scrapy是一个功能非常强大的爬虫框架,它不仅能便捷地构建request,还有强大的selector能够方便地解析response,然而它最受欢迎的还是它的性能,即抓取和解析的速度,它的downloader是多线程的,request是异步调度和处理的。这两点使它的爬取速度非常之快。另外还有内置的logging,exception,shell等模块,为爬取工作带来了很多便利。
以下关于scrapy的问题:
1.scrapy的基本结构(五个部分)都是什么?,请求发出去的整个流程?
scrapy由Spider、Engine、Scheduler、Downloader、Item Pipline五个部分组成。发送请求主要由如下几个步骤:
- 首先Spiders(爬虫)将需要发送请求的url(requests)到Engine(引擎)。
- Engine(引擎)把request交给Scheduler(调度器)。
- Scheduler经过排序,入队处理后,重新把request发送到Engine。
- Engine把request请求通过DownloaderMiddlewares(可选,主要有User_Agent, Proxy代理)交给Downloader(下载器)。
- Downloader向网站发送请求,并接受下载响应(Response),将Response返回给Engine。
- Response由Engine,经过SpiderMiddlewares(可选)发送到Spiders开始解析。
- 解析数据完成后,将所需的Items原路返回到Engine。
- Engine将Items发送到ItemPipeline(可以是本地,可以是数据库),提取下一个url再次进行循环。
2.scrapy的去重原理 (指纹去重到底是什么原理)
对于每一个url的请求,调度器都会根据请求得相关信息加密得到一个指纹信息,并且将指纹信息和set()集合中的指纹信息进行比对,如果set()集合中已经存在这个数据,就不在将这个Request放入队列中。如果set()集合中没有存在这个加密后的数据,就将这个Request对象放入队列中,等待被调度。
3.scrapy中间件有几种类,你用过那些中间件(详情)
scrapy中间件有Spider Middlewares 和 Downloader Middlewares两种(中间件原理),将fake-useragent和IP代理集成到Middlewares中,使Spider在发送request时主动更换User-Agent和IP。
4.scrapy中间件在哪里起的作用(面向切面编程)
1.爬虫中间件Spider Middleware:主要功能是在爬虫运行过程中进行一些处理.
2.下载器中间件Downloader Middleware:主要功能在请求到网页后,页面被下载时进行一些处理.
代理问题
1.为什么会用到代理?
网站的反爬虫策略会检测到同一个IP访问次数频率过快,从而禁止该IP的访问。因此爬虫过程中需要IP代理避免该问题。
2.代理怎么使用(具体代码,请求在什么时候添加的代理)
class RandomProxyMiddleware(object): #动态设置ip代理 def process_request(self, request, spider): get_ip = GetIP() #GetIP是获取代理IP的方法 request.meta["proxy"] = get_ip.get_random_ip()
该方法需要在Spider Middlewares中添加,为了在给网站发送请求前获得有效的代理IP。
3.代理失效了怎么处理?
事先用检测代码检测可用的代理,每隔一段时间更换一次代理,如果出现302等状态码,则立即更换下一个可用的IP。
四.验证码处理
1.登陆验证码处理
- 图片验证码:先将验证码图片下载到本地,然后使用云打码识别;
- 滑动验证码:使用selenium模拟人工拖动,对比验证图片的像素差异,找到滑动的位置然后获取它的location和size,然后 top,bottom,left,right = location['y'] ,location['y']+size['height']+ location['x'] + size['width'] ,然后截图,最后抠图填入这四个位置就行。
2.爬取速度过快出现的验证码处理
设置setting.py中的DOWNLOAD_DELAY,降低爬取速度;
- 用xpath获取验证码关键字,当出现验证码时,识别验证码后再继续运行。
3.如何用机器识别验证码
模拟登陆问题
1.模拟登陆流程
- 加载浏览器driver;
- 获取登录页面;
- 使用css选择器或者xpath找到账号和密码输入框,并发送账号和密码;
- 如果出现验证码则需要先识别验证码,在模拟输入验证码或者模拟鼠标拖动;
- 使用css选择器或者xpath找到登录按钮,使用click模拟点击;
2.cookie如何处理
- 采用selenium自动登录获取cookie,保存到文件;
- 读取cookie,比较cookie的有效期,若过期则再次执行步骤1;
- 在请求其他网页时,填入cookie,实现登录状态的保持;
3.如何处理网站传参加密的情况
加密的三种情况:
- 加密+访问次数限制+每个页面相关信息的条目需要点详情进行二次请求;
- 复杂的加密算法进行参数+时间戳+sig值,后台进行 参数+时间限制;
- 定时同步cookie+每个界面一个cookie。
破解方法:
- 使用selenium模拟点击获取详情页面;
- 获取其相应的api接口,GET接口URL,获取它的json表格内容;
- 反向分析网页JS加载内容;
六.分布式
1.分布式原理
分布式爬虫主要由主机与从机,我们把自己的核心服务器(主机)称为 master,而把用于跑爬虫程序的机器(从机)称为 slave。
我们首先给爬虫一些start_urls,spider 最先访问 start_urls 里面的 url,再根据我们的 parse 函数,对里面的元素、或者是其他的二级、三级页面进行抓取。而要实现分布式,只需要在这个starts_urls里面做文章就行了。进一步描述如下:
- master 产生 starts_urls,url 会被封装成 request 放到 redis 中的 spider:requests,总的 scheduler 会从这里分配 request,当这里的 request 分配完后,会继续分配 start_urls 里的 url。
- slave 从 master 的 redis 中取出待抓取的 request,下载完网页之后就把网页的内容发送回 master 的 redis,key 是 spider:items。scrapy 可以通过 settings 来让 spider 爬取结束之后不自动关闭,而是不断的去询问队列里有没有新的 url,如果有新的 url,那么继续获取 url 并进行爬取,所以这一过程将不断循环。
- master 里的 reids 还有一个 key 是 “spider:dupefilter” 用来存储抓取过的 url 的 fingerprint(使用哈希函数将url运算后的结果),防止重复抓取,只要 redis 不清空,就可以进行断点续爬。
2.分布式如何判断爬虫已经停止了
3.分布式去重原理
可以用布隆过滤器(Bloom filiter)进行去重。
七.数据存储和数据库问题
1.关系型数据库和非关系型数据库的区别
https://blog.csdn.net/longxingzhiwen/article/details/53896702
2.爬下来数据你会选择什么存储方式,为什么
3.各种数据库支持的数据类型,和特点,比如:redis如何实现持久化,mongodb是否支持事物等。。
八.python基础问题
1.python2和python3的区别,如何实现python2代码迁移到python3环境
区别:字符串类型、默认字符、print方法、除法的数字类型、导入方式、继承类、元类声明、异常处理、字典、模块合并、部分模块重命名(详情)
代码迁移:python3有个内部工具叫做2to3.py,位置在Python3/tool/script文件夹。
首先CD到这个文件夹,然后调用
py 2to3.py -w f:/xxxx/xxx.py
2.python2和python3的编码方式有什么差别?
在python2中主要有str和unicode两种字符串类型,而到python3中改为了bytes和str,并且一个很重要的分别是,在python2中如果字符串是ascii码的话,str和unicode是可以直接进行连接和比较,但是到python3中就不行了,bytes和str是两个独立的类型。另一个重要的是python2中不管是str还是unicode都可以直接写入文件,而不需要加上它是不是str的类型写入方式,但是在python3中如果是写或者读bytes类型就必需带上’b’.
3.迭代器,生成器,装饰器
4.python的数据类型
九.协议问题
1.http协议,请求由什么组成,每个字段分别有什么用,https和http有什么差距?
请求行(request line)、请求头部(header)、空行和请求数据四个部分组成(详情);
- 请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本;
- 请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息;
- 空行,请求头部后面的空行是必须的;
- 请求数据也叫主体,可以添加任意的其他数据;
HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS和HTTP的区别主要如下:
- https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
- http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
- http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
2.证书问题
https://blog.csdn.net/fangqun663775/article/details/55189107
3.TCP,UDP各种相关问题
https://blog.csdn.net/xiaobangkuaipao/article/details/76793702
十.数据提取问题
1.主要使用什么样的结构化数据提取方式(详情)?
JSON文件
- JSON Path
- 转化为Python类型进行操作(json类)
XML文件
- 转化为Python类型(xmltodict)
- XPath
- CSS选择器
- 正则表达式
2.正则的使用
参考:http://tool.oschina.net/uploads/apidocs/jquery/regexp.html
3.动态加载的数据如何提取?
- selenium获取;
- 分析请求页面,获取它的js请求文件;
4.json数据如何提取
- 采用正则表达式解析:获取整个json数据后,采用正则表达式匹配到关键词;
- 基于json格式进行获取:json的数据格式与python的dict是有极大的类似之处。在python的 json 这个包里面提供了两个经典的预处理方法:json.dumps:将ptyhon的dict转成str,json.loads:将str转成python的dict类型;
---