首页 > 其他 > 详细

爬虫面试题

时间:2020-03-04 14:27:02      阅读:88      评论:0      收藏:0      [点我收藏+]

1.爬虫的基本流程?

1、通过http向目标站点发起请求,即发送一个Request,请求可以包含额外的headers等信息,等待服务器响应
2、如果服务器能正常响应,会得到一个Response,Response的内容就是要获取的页面内容
3、解析内容:正则表达式、页面解析库、json
4、保存数据:文本或者存入数据库

2.什么是Request和Response?

本地 向 服务器 发送Request,服务器根据请求返回一个Response,页面就显示出来了
1、浏览器发送消息给该网址所在的服务器,这个过程叫做Http Request
2、服务器收到浏览器发送的消息后,能够根据浏览器发送消息的内容,做相应处理,然后把消息回传给浏览器,这个过程叫做HTTP Response
3、浏览器收到服务器的Response消息后,会对信息进行相应处理,然后显示

3.Request中包含什么呢?

1、请求方式:主要有GET和POST两种方式,POST请求的参数不会包含在url里面
2、请求URL

URL:统一资源定位符,如一个网页文档、一张图片、一个视频等都可以用URL来唯一确定
3、请求头信息,包含了User-Agent(浏览器请求头)、Host、Cookies信息
4、请求体,GET请求时,一般不会有,POST请求时,请求体一般包含form-data

4.Response中包含什么信息?

1、响应状态:状态码 正常响应200 重定向
2、响应头:如内容类型、内容长度、服务器信息、设置cookie等
3、响应体信息:响应源代码、图片二进制数据等等

5.常见的http状态码

200状态码 服务器请求正常
301状态码:被请求的资源已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302状态码:请求的资源临时从不同的URI响应请求,但请求者应继续使用原有位置来进行以后的请求
401状态码:请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
403状态码:服务器已经理解请求,但是拒绝执行它。与401响应不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交。
404状态码:请求失败,请求所希望得到的资源未被在服务器上发现。
500状态码:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器的程序码出错时出现。
503状态码:由于临时的服务器维护或者过载,服务器当前无法处理请求。

6.HTTP 的请求和响应都包含哪些内容

HTTP请求头:

Accept:浏览器能够处理的内容类型
Accept-Charset:浏览器能够显示的字符集
Accept-Encoding:浏览器能够处理的压缩编码
Accept-Language:浏览器当前设置的语言
Connection:浏览器与服务器之间连接的类型
Cookie:当前页面设置的任何Cookie
Host:发出请求的页面所在的域
Referer:发出请求的页面的URL
User-Agent:浏览器的用户代理字符串
HTTP响应头部信息:
Date:表示消息发送的时间,时间的描述格式由rfc822定义
server:服务器名字。
Connection:浏览器与服务器之间连接的类型
content-type:表示后面的文档属于什么MIME类型
Cache-Control:控制HTTP缓存

7. 你遇到的反爬虫策略有哪些?及应对策略有什么?

反爬虫策略

1.通过headers反爬虫
2.基于用户行为的发爬虫:例如同一IP短时间内多次访问同一页面,或者同一账户短时间内多次进行相同操作。
3.动态网页反爬虫,例如:我们需要爬取的数据是通过ajax请求得到,或者通过JavaScript生成的对部分数据进行加密处理的,例如:我们要抓的数据一部分能够抓到,另外的部分加密处理了,是乱码的。
应对策略:
1.对于基本网页的抓取可以自定义headers,添加headers的数据,代理来解决。
2.有些网站的数据抓取必须进行模拟登陆才能抓取到完整的数据,所以要进行模拟登陆。
3.对于限制抓取频率的,可以设置抓取的频率降低一些,
4.对于限制ip抓取的可以使用多个代理ip进行抓取,轮询使用代理
5.针对动态网页的可以使用selenium+phantomjs进行抓取,但是比较慢,所以也可以使用查找接口的方式进行抓取。
6.对部分数据进行加密的,可以使用selenium进行截图,饭后使用python自带的 pytesseract库进行识别,但是比较慢最直接的方法是找到加密的方法进行逆向推理。

8. 谈一谈你对 Selenium 和 PhantomJS 了解

Selenium 是一个Web 的自动化测试工具,可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是我们有时候需要让它内嵌在代码中运行,所以我们可以用一个叫 PhantomJS 的工具代替真实的浏览器。Selenium库里有个叫 WebDriver 的API。WebDriver 有点儿像可以加载网站的浏览器,但是它也可以像BeautifulSoup 或者其他Selector 对象一样用来查找页面元素,与页面上的元素进行交互 (发送文本、点击等),以及执行其他动作来运行网络爬虫。
PhantomJS是一个基于 Webkit 的“无界面”(headless)浏览器,它会把网站加载到内存并执行页面上的 JavaScript,因为不会展示图形界面,所以运行起来比完整的浏览器要高效。相比传统的Chrome或 Firefox 浏览器等,资源消耗会更少。
如果我们把 Selenium 和 PhantomJS 结合在一起,就可以运行一个非常强大的网络爬虫了,这个爬虫可以处理 JavaScrip、Cookie、headers,以及任何我们真实用户需要做的事情。主程序退出后,selenium 不保证 phantomJS 也成功退出,最好手动关闭 phantomJS 进程。(有可能会导致多个 phantomJS 进程运行,占用内存)。WebDriverWait 虽然可能会减少延时,但是目前存在 bug(各种报错),这种情况可以采用 sleep。phantomJS爬数据比较慢,可以选择多线程。如果运行的时候发现有的可以运行,有的不能,可以尝试将 phantomJS 改成 Chrome。

9. 为什么 requests 请求需要带上 header?

原因是:模拟浏览器,欺骗服务器,获取和浏览器一致的内容
header 的形式:字典
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
用法: requests.get(url,headers=headers)。

10.Scrapy优缺点:

优点:

1.scrapy 是异步的
2.采取可读性更强的xpath代替正则
3.强大的统计和log系统
4.同时在不同的url上爬行
5.支持shell方式,方便独立调试
6.写middleware,方便写一些统一的过滤器
6.通过管道的方式存入数据库
缺点:
1.基于python的爬虫框架,扩展性比较差
2.基于twisted框架,运行中的exception是不会干掉reactor,并且异步框架出错后是不会停掉其他任务的,数据出错后难以察觉

12. 简述 移动端 app 数据的抓取流程

1、例如:爬取手机淘宝, 核心还是一个 WEB页面:https://m.taobao.com/#index
2、有很多资讯类的 APP,核心都是一个 WEB页面。直接用爬虫的方法抓就可以了。
3、非 WEB页面的 APP,用 APP自动化的一些东西试试
4、不然就只有抓包了。

13.在 requests 模块中,requests.content 和 requests.text 什么区别?

1.response.content:  这个是直接从网络上面抓取的数据,没有经过任何解码,所以是一个bytes类型,其实在硬盘上和在网络上传输的字符串都是bytes类型
2.response.text:  这个是str的数据类型,是requests库将response.content进行解码的字符串,解码需要指定一个编码方式,requests会根据自己的猜测来判断编码的方式,所以有时候可能会猜测错误,就会导致解码产生乱码,这时候就应该使用‘response.content.decode(‘utf-8‘)‘进行手动解码

14.说一说 scrapy 的工作流程

技术分享图片

15.scrapy 的去重原理

1.Scrapy本身自带有一个中间件;
2.scrapy源码中可以找到一个dupefilters.py去重器;
3.需要将dont_filter设置为False开启去重,默认是false去重,改为True,就是没有开启去重;
4 .对于每一个url的请求,调度器都会根据请求得相关信息加密得到一个指纹信息,并且将指纹信息和set()集合中的指纹信息进 行 比对,如果set()集合中已经存在这个数据,就不在将这个Request放入队列中;5.如果set()集合中没有存在这个加密后的数据,就将这个Request对象放入队列中,等待被调度。

15.scrapy 中间件有几种类,你用过哪些中间件

概述:在scrapy运行的整个过程中,对scrapy框架运行的某些步骤做一些适配自己项目的动作.
例如scrapy内置的HttpErrorMiddleware,可以在http请求出错时做一些处理.
中间件的分类:scrapy的中间件理论上有三种(Schduler Middleware,Spider Middleware,Downloader Middleware),在应用上一般有以下两种
? ? ? ?1.爬虫中间件Spider Middleware
? ? ? ?主要功能是在爬虫运行过程中进行一些处理.,downloadtimeout,RobotsTxtMiddleware
,HttpAuthMiddleware,DownloaderStats
  2.下载器中间件Downloader Middleware
? ? ? ? ?主要功能在请求到网页后,页面被下载时进行一些处理,如:DownloaderMiddleware,user-agent中间件,代理ip中间件,重试中间件

17.scrapy 和 scrapy-redis 有什么区别?为什么选择 redis 数据库?

1) scrapy是一个Python爬虫框架,爬取效率极高,具有高度定制性,但是不支持分布式。而scrapy-redis一套基于redis数据库、运行在scrapy框架之上的组件,可以让scrapy支持分布式策略,Slaver端共享Master端redis数据库里的item队列、请求队列和请求指纹集合。
2)?为什么选择redis数据库,因为redis支持主从同步,而且数据都是缓存在内存中的,所以基于redis的分布式爬虫,对请求和数据的高频读取效率非常高。

18. 分布式爬虫原理?

scrapy-redis实现分布式,其实从原理上来说很简单,这里为描述方便,我们把自己的核心服务器称为 master,而把用于跑爬虫程序的机器称为 slave。
我们知道,采用 scrapy 框架抓取网页,我们需要首先给定它一些 start_urls,爬虫首先访问 start_urls里面的 url,再根据我们的具体逻辑,对里面的元素、或者是其他的二级、三级页面进行抓取。而要实现分布式,我们只需要在这个 starts_urls 里面做文章就行了。
我们在 master 上搭建一个 redis 数据库(注意这个数据库只用作 url 的存储,不关心爬取的具体数据,不要和后面的 mongodb 或者 mysql 混淆),并对每一个需要爬取的网站类型,都开辟一个单独的列表字段。通过设置 slave 上 scrapy-redis 获取 url 的地址为 master 地址。这样的结果就是,尽管有多个 slave,然而大家获取 url 的地方只有一个,那就是服务器 master 上的 redis 数据库。并且,由于 scrapy-redis 自身的队列机制,slave 获取的链接不会相互冲突。这样各个 slave 在完成抓取任务之后,再把获取的结果汇总到服务器上(这时的数据存储不再在是 redis,而是 mongodb 或者mysql等存放具体内容的数据库了)这种方法的还有好处就是程序移植性强,只要处理好路径问题,把 slave 上的程序移植到另一台机器上运行,基本上就是复制粘贴的事情。

19.分布式爬虫主要解决什么问题

ip、带宽、cpu、io

20.robots协议是什么?

Robots协议(也称为爬虫协议、爬虫规则、机器人协议等)也就是robots.txt,网站通过robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。Robots协议是网站国际互联网界通行的道德规范,其目的是保护网站数据和敏感信息、确保用户个人信息和隐私不被侵犯。因其不是命令,故需要搜索引擎自觉遵守。

21. mysql的索引在什么情况下失效

1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
2.对于多列索引,不是使用的第一部分,则不会使用索引
3.like查询以%开头
4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
5.如果mysql估计使用全表扫描要比使用索引快,则不使用索引

22.MySQL 有什么引擎,各引擎之间有什么区别?

主要 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%‘

23.HTTPS 是如何实现安全传输数据的

客户端(通常是浏览器)先向服务器发出加密通信的请求
服务器收到请求,然后响应
客户端收到证书之后会首先会进行验证
服务器收到使用公钥加密的内容,在服务器端使用私钥解密之后获得随机数pre-master secret,然后根据radom1、radom2、pre-master secret通过一定的算法得出session Key和MAC算法秘钥,作为后面交互过程中使用对称秘钥。同时客户端也会使用radom1、radom2、pre-master secret,和同样的算法生成session Key和MAC算法的秘钥。
然后再后续的交互中就使用session Key和MAC算法的秘钥对传输的内容进行加密和解密。

24. 如何循环抓取一个网站的 1000 张图片?

流程大概是这样
找到所有页数
---- 遍历所有的页数
---- 遍历当前页的所有相册 ( 给每个相册建立一个目录 )
---- 遍历当前相册的所有图片 ( 遍历此相册的所有页 ( 遍历当前页的所有照片并
找到图片的 url))
---- 获得图片 url 就存起来 , 然后通过图片 url 下载图片。
---- 引用计数当图片下载量达到
1000 张时,停止爬取

25.登陆古诗文网:手动识别验证码。完成模拟登陆。

import requests
from bs4 import BeautifulSoup
import urllib.request

import pytesseract
from PIL import Image
from PIL import ImageEnhance

def shibie(filepath):
    # 打开图片
    img = Image.open(filepath)

    img = img.convert('RGB')
    enhancer = ImageEnhance.Color(img)
    enhancer = enhancer.enhance(0)
    enhancer = ImageEnhance.Brightness(enhancer)
    enhancer = enhancer.enhance(2)
    enhancer = ImageEnhance.Contrast(enhancer)
    enhancer = enhancer.enhance(8)
    enhancer = ImageEnhance.Sharpness(enhancer)
    img = enhancer.enhance(20)

    # 处理图片,提高图片的识别率
    # 转化为灰度图片
    img = img.convert('L')
    # img.show()

    # 对图片进行二值化处理
    threshold = 140
    table = []
    for i in range(256):
        if i < threshold:
            table.append(0)
        else:
            table.append(1)
    out = img.point(table, '1')
    # out.show()

    # exit()

    # 将图片转化为RGB模式
    img = img.convert('RGB')

    return pytesseract.image_to_string(img)

i = 0
    
while 1:
    # 创建一个会话
    s = requests.Session()

    # 发送get请求
    deng_url = 'https://so.gushiwen.org/user/login.aspx?from=http://so.gushiwen.org/user/collect.aspx'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36',
    }
    r = s.get(deng_url, headers=headers)

    # 生产soup对象
    soup = BeautifulSoup(r.text, 'lxml')
    # 获取验证码的url
    image_src = 'https://so.gushiwen.org' + soup.find('img', id='imgCode')['src']
    # 将这个图片下载到本地
    r = s.get(image_src, headers=headers)
    with open('code.png', 'wb') as fp:
        fp.write(r.content)

    # 获取页面中隐藏的两个数据
    view_state = soup.find('input', id='__VIEWSTATE')['value']
    view_generator = soup.find('input', id='__VIEWSTATEGENERATOR')['value']

    # code = input('请输入验证码')
    code = shibie('code.png')

    # 抓包,抓取post请求,然后通过代码模拟发送post请求
    post_url = 'https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx'
    data = {
        '__VIEWSTATE': view_state,
        '__VIEWSTATEGENERATOR': view_generator,
        'from': 'http://so.gushiwen.org/user/collect.aspx',
        'email': '1090509990@qq.com',
        'pwd': '123456',
        'code': code,
        'denglu': '登录',
    }

    r = s.post(url=post_url, headers=headers, data=data)
    i += 1
    
    print('这是第%s次登录' % i)

    # print(r.text)
    if '退出登录' in r.text:
        break

print('登录成功')
python

26.bs4方法学习

html插件   emmet
    (1)根据标签名查找
        soup.a   查找得到的是第一个符合要求的标签
    (2)获取属性、内容
        soup.a['href']
        soup.a.attrs  所有的属性和值,返回了一个字典

        soup.a.string
        soup.a.text
        soup.a.get_text()
            获取标签内容,如果标签里面只有内容,这三个都是一样的
            如果标签里面还有标签,那么string获取的为None,另外两个获取的是纯文本信息
    (3)find
        返回一个对象,这个对象可以直接获取其属性和文本内容
        soup.find('a')  根据标签名查找,找到的是第一个
        soup.find('a', id='xxx')
        soup.find('a', class_='xxx')  找到的是第一个
        soup.find('a', title='xxx')   找到的是第一个
    (4)find_all
        返回的是一个列表,列表里面都是每一个对象
        find_all('a')
        find_all(['a', 'b'])
        find_all('b', class_='xxx')  找到所有的指定class的标签
        find_all('b', class_='xxx', limit=2)  只取前两个
    (5)select
        返回的是一个列表,列表里面都是对象
        选择,选择器的东西
        css,层叠样式表,jquery里面也有
        常见的选择器:
            标签选择器  
            类选择器
                .类名
            id选择器
                #id名
            属性选择器
                input[name=user]
                a[title=lala]
            层级选择器
                div .dudu #hehe a 
                    【注】后面的节点是前面节点子孙节点就可以
                div > .dudu > #hehe > div
                    【注】后面的节点必须是前面节点的直接子节点
        【注1】select方法返回的是一个列表
        【注2】节点对象也拥有select方法
    下载三国演义
        滚滚长江东逝水,浪花淘尽英雄,是非成败转头空,青山依旧在,几度夕阳红
        白发渔樵江渚上,惯看秋月春风,一壶浊酒喜相逢,古今多少事,都付笑谈中
    智联招聘
        https://sou.zhaopin.com/jobs/searchresult.ashx?jl=%E5%8C%97%E4%BA%AC&kw=c&p=2
        jl : 城市定位
        kw : 岗位关键字
        p : 搜索页码
        
        内容有:职位名称、公司名称、职位月薪、工作地点、发布时间
python

27.xpath学习

xml和html的不同
    (1)html标签被预定义,xml标签需要自己定义
    (2)html设计用来显示数据,xml设计用来传输数据
    xpath教程
        常用路径表达式
        / : 从根节点开始查找
        // : 从任意位置开始查找
        . : 从当前节点开始查找
        .. : 从上一级节点开始查找
        @ :选取指定属性
        
        bookstore/book : 查找bookstore下面的所有book节点,该book必须是bookstore的直接子节点
        //book : 查找所有的book
        bookstore//book : 查找bookstore下面的所有book节点,但是该book是bookstore的子节点或者子孙节点
        //@lang : 查找所有有lang属性的节点
        
        bookstore/book[1] : 取出bookstore下面的第一个本book
        bookstore/book[last()] : 取出bookstore下面的最后一个本book
        bookstore/book[last()-1] : 取出bookstore下面的倒数第二本book
        //title[@lang] : 查找所有的有lang属性的title节点
        //title[@lang='eng'] :查找所有lang属性为eng的title节点
        
        * :匹配所有的节点
        @* : 匹配所有的属性节点
    
    xpath在html中应该如何使用
        插件的安装
        点击三个点==》更多工具==》扩展程序,将xpath.crx拖到谷歌窗口即可安装成功,成功之后,在浏览器右上角有×的标志
        启动和关闭插件
            ctrl+shift+x
        xpath使用
            属性定位
                input[@id="kw"]
            层级定位、索引定位
                //div[@class="head_wrapper"]/div[@id="u1"]/a[1]
                //div[@class="head_wrapper"]//a
            模糊匹配
                contains
                    //a[contains(@class,"lb")]
                    查找所有的a,class属性值包含lb的a
                    //a[contains(text(),"新")]
                    查找所有的a,文本内容包含 新 的a
                starts-with
                    //a[starts-with(@class,"lb")]
                    查找所有的a。class属性值以lb开头的
                    //a[starts-with(text(),"更多")]
                    查找所有的a,文本内容以更多开头
            获取文本内容
                //div[@id="u1"]/a[1]/text()
            获取属性值
                //div[@id="u1"]/a[2]/@href
                //div[@id="u1"]/img[1]/@src
        代码学习
            pip install lxml
python

28.正则表达式

为什么引入正则表达式?写一个规则,这个规则就能匹配所有符合这个规则的字符串
    规则:
        单字符匹配
            \d : 一个数字字符   digit    (牢记)
            \D : 非数字字符
            \w : 数字、字母、下划线  word  (牢记)
            \W : 非\w
            \s : 匹配任意空白字符    space  (牢记)
            \S : 非空白字符
            [] : [1-5]  [a-d]  [aeiou]   (牢记)
                 [0-9]  [a-zA-Z_0-9]
            .  : 匹配除了换行符以外任意字符  (牢记)
        数量修饰
            {m} : 修饰前面的字符出现m次
            {m,} : 修饰前面的字符出现至少m次
            '1234567'  \d{3,5}  贪婪
            {m,n} : 修饰前面的字符最少出现m次,最多n次
            {0,} : *  能够出现任意多次
            {1,} : +  至少一次
            {0,1} : ?  可有可无
        边界:
            ^ : 以某某开头
            $ :以某某结尾
        分组(子模式)
            ()  由小括号括起来的正则
            视为一个整体     (\d{3}){2}
            子模式
                \1  \2
        贪婪模式
            .*            尽可能多的匹配
            .+
            .*?   非贪婪  尽可能少的匹配
            .+?   非贪婪
        修正符
            re.I : 忽略大小写
            re.M : 多行模式
            re.S : 单行模式
    导入一个模块   re
        re.compile() : 生成正则对象(牢记)
        re.match() :从字符串开头匹配
        re.search() : 从字符串任意位置匹配,只找一个(牢记)
        re.findall() :从字符串中查找所有匹配的内容(牢记)
            返回一个列表,只找到子模式匹配到的内容
        re.sub() :正则替换
正则匹配邮箱: /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;  
正则匹配手机号码: 1\d{10}
python

爬虫面试题

原文:https://www.cnblogs.com/lpdeboke/p/12408497.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!