目录
1. scrapy 和 scrapy-redis 有什么区别?为什么选择 redis 数据库?
2. 用过的爬虫框架或者模块有哪些?谈谈他们的区别或者优缺点?
3. 常用的 mysql 引擎有哪些?各引擎间有什么区别?
4. 描述下 scrapy 框架运行的机制?
5. 什么是关联查询,有哪些?
6. 写爬虫是用多进程好?还是多线程好? 为什么?
7. 数据库的优化?
8. 常见的反爬虫和应对方法?
9. 分布式爬虫主要解决什么问题?
10. 爬虫过程中验证码怎么处理?
1) scrapy 是一个 Python 爬虫框架,爬取效率极高,具有高度定制性,但是不支持分布式。而 scrapy-redis 一套基于 redis 数据库、运行在 scrapy 框架之上的组件,可以让 scrapy 支持分布式策略,Slaver 端共享 Master 端 redis 数据库里的 item 队列、请求队列和请求指纹集合。
2) 为什么选择 redis 数据库,因为 redis 支持主从同步,而且数据都是缓存在内存中的,所以基于 redis 的分布式爬虫,对请求和数据的高频读取效率非常高。
Python自带:urllib,urllib2
第三方:requests
框架:Scrapy
urllib 和 urllib2 模块都做与请求 URL 相关的操作,但他们提供不同的功能。
urllib2:urllib2.urlopen 可以接受一个 Request 对象或者url,(在接受 Request 对象时候,并以此可以来设置一个 URL 的headers),urllib.urlopen 只接收一个 url
urllib 有 urlencode,urllib2 没有,因此总是 urllib 与 urllib2 常会一起使用的原因
scrapy 是封装起来的框架,他包含了下载器,解析器,日志及异常处理,基于多线程, twisted 的方式处理,对于固定单个网站的爬取开发,有优势,但是对于多网站爬取 100个网站,并发及分布式处理方面,不够灵活,不便调整与括展。
request 是一个 HTTP 库, 它只是用来,进行请求,对于 HTTP 请求,他是一个强大的库,下载,解析全部自己处理,灵活性更高,高并发与分布式部署也非常灵活,对于功能可以更好实现.
Scrapy 优缺点:
优点:scrapy 是异步的
采取可读性更强的 xpath 代替正则
强大的统计和 log 系统
同时在不同的 url 上爬行
支持 shell 方式,方便独立调试
写 middleware,方便写一些统一的过滤器
通过管道的方式存入数据库
缺点:基于 python 的爬虫框架,扩展性比较差
基于 twisted 框架,运行中的 exception 是不会干掉 reactor,并且异步框架出错后是不会停掉其他任务的,数据出错后难以察觉。
主要 MyISAM 与 InnoDB 两个引擎,其主要区别如下:
1). InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而 MyISAM就不可以了;
2). MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用;
3). InnoDB 支持外键,MyISAM 不支持;
4). MyISAM 是默认引擎,InnoDB 需要指定;
5). InnoDB 不支持 FULLTEXT 类型的索引;
6). InnoDB 中不保存表的行数,如 select count(*) from table 时,InnoDB;需要扫描一遍整个表来计算有多少行,但是 MyISAM 只要简单的读出保存好的行数即可。注意的是,当 count(*) 语句包含 where 条件时 MyISAM 也需要扫描整个表;
7). 对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM 表中可以和其他字段一起建立联合索引;
8). 清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表;
9). InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a = 1 where user like '%lee%'
从 start_urls 里获取第一批url并发送请求,请求由引擎交给调度器入请求队列,获取完毕后,调度器将请求队列里的请求交给下载器去获取请求对应的响应资源,并将响应交给自己编写的解析方法做提取处理:
1). 如果提取出需要的数据,则交给管道文件处理;
2). 如果提取出 url,则继续执行之前的步骤(发送 url 请求,并由引擎将请求交给调度器入队列...),直到请求队列里没有请求,程序结束。
将多个表联合起来进行查询,主要有内连接、左连接、右连接、全连接(外连接)
IO密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,可以不浪费CPU的资源,从而能提升程序执行效率)。在实际的数据采集过程中,既考虑网速和响应的问题,也需要考虑自身机器的硬件情况,来设置多进程或多线程
1). 优化索引、SQL 语句、分析慢查询;
2). 设计表的时候严格根据数据库的设计范式来设计数据库;
3). 使用缓存,把经常访问到的数据而且不需要经常变化的数据放在缓存中,能节约磁盘IO;
4). 优化硬件;采用SSD,使用磁盘队列技术(RAID0,RAID1,RDID5)等;
5). 采用MySQL 内部自带的表分区技术,把数据分层不同的文件,能够提高磁盘的读取效率;
6). 垂直分表;把一些不经常读的数据放在一张表里,节约磁盘I/O;
7). 主从分离读写;采用主从复制把数据库的读操作和写入操作分离开来;
8). 分库分表分机器(数据量特别大),主要的的原理就是数据路由;
9). 选择合适的表引擎,参数上的优化;
10). 进行架构级别的缓存,静态化和分布式;
11). 不采用全文索引;
12). 采用更快的存储方式,例如 NoSQL存储经常访问的数据
1). 通过Headers反爬虫
从用户请求的Headers反爬虫是最常见的反爬虫策略。很多网站都会对Headers的User-Agent进行检测,还有一部分网站会对Referer进行检测(一些资源网站的防盗链就是检测Referer)。如果遇到了这类反爬虫机制,可以直接在爬虫中添加Headers,将浏览器的User-Agent复制到爬虫的Headers中;或者将Referer值修改为目标网站域名。对于检测Headers的反爬虫,在爬虫中修改或者添加Headers就能很好的绕过。
2). 基于用户行为反爬虫
还有一部分网站是通过检测用户行为,例如同一 IP 短时间内多次访问同一页面,或者同一账户短时间内多次进行相同操作。
大多数网站都是前一种情况,对于这种情况,使用 IP 代理就可以解决。可以专门写一个爬虫,爬取网上公开的代理 ip,检测后全部保存起来。这样的代理 ip 爬虫经常会用到,最好自己准备一个。有了大量代理ip后可以每请求几次更换一个 ip,这在requests 或者 urllib2 中很容易做到,这样就能很容易的绕过第一种反爬虫。
对于第二种情况,可以在每次请求后随机间隔几秒再进行下一次请求。有些有逻辑漏洞的网站,可以通过请求几次,退出登录,重新登录,继续请求来绕过同一账号短时间内不能多次进行相同请求的限制。
3). 动态页面的反爬虫
上述的几种情况大多都是出现在静态页面,还有一部分网站,我们需要爬取的数据是通过 ajax 请求得到,或者通过 JavaScript 生成的。首先用 Fiddler 对网络请求进行分析。如果能够找到 ajax 请求,也能分析出具体的参数和响应的具体含义,我们就能采用上面的方法,直接利用 requests 或者 urllib2 模拟 ajax 请求,对响应的 json 进行分析得到需要的数据。
能够直接模拟 ajax 请求获取数据固然是极好的,但是有些网站把 ajax 请求的所有参数全部加密了。我们根本没办法构造自己所需要的数据的请求。这种情况下就用 selenium + phantomJS,调用浏览器内核,并利用 phantomJS 执行 js 来模拟人为操作以及触发页面中的 js 脚本。从填写表单到点击按钮再到滚动页面,全部都可以模拟,不考虑具体的请求和响应过程,只是完完整整的把人浏览页面获取数据的过程模拟一遍。
用这套框架几乎能绕过大多数的反爬虫,因为它不是在伪装成浏览器来获取数据(上述的通过添加 Headers 一定程度上就是为了伪装成浏览器),它本身就是浏览器,phantomJS 就是一个没有界面的浏览器,只是操控这个浏览器的不是人。利 selenium + phantomJS 能干很多事情,例如识别点触式(12306)或者滑动式的验证码,对页面表单进行暴力破解等。
1). ip
2). 带宽
3). cpu
4). io
1). scrapy自带
2). 付费接口
文章来源