美文网首页
python爬虫 面试常见问题

python爬虫 面试常见问题

作者: 王镇_ee87 | 来源:发表于2021-01-04 08:48 被阅读0次

    frida 动态插桩工具 插入一些代码到原生的app的内存空间,原生平台可以是 mac linux win android ios 而且 frida是开源的

    Xposed 框架 核心思想在于将Java层普通函数注册成本地JNI方法,以此来变相实现hook机制(放在文章开头的话很重要哦,记住!)

    两种方法分别使用了Android、python+JS作为开发语言进行hook。

    python中requests里 .text和.content方法的区别
    .text是现成的字符串,
    .content还要编码,
    但是.text不是所有时候显示都正常,
    这是就需要用.content进行手动编码。
    
    异步与非阻塞的区别
    异步:调用在发出之后,这个调用就直接返回,不管有无结果
    非阻塞:关注的是程序在等待调用结果(消息,返回值)时的状态,指在不能立刻得到结果之前,该调用不会阻塞当前线程
    
    scrapy详细工作流程
    1.首先Spiders(爬虫)将需要发送请求的url(requests)经ScrapyEngine(引擎)交给Scheduler(调度器)。
    
    2.Scheduler(排序,入队)处理后,经ScrapyEngine,DownloaderMiddlewares(可选,主要有User_Agent, Proxy代理)交给Downloader。
    
    3.Downloader向互联网发送请求,并接收下载响应(response)。将响应(response)经ScrapyEngine,SpiderMiddlewares(可选)交给Spiders。     
    
    4.Spiders处理response,提取数据并将数据经ScrapyEngine交给ItemPipeline保存(可以是本地,可以是数据库)。
    
    5.提取url重新经ScrapyEngine交给Scheduler进行下一个循环。直到无Url请求程序停止结束。
    

    Scrapy去重原理

    1.Scrapy本身自带有一个中间件;
    2.scrapy源码中可以找到一个dupefilters.py去重器;
    3.需要将dont_filter设置为False开启去重,默认是True,没有开启去重;
    4.对于每一个url的请求,调度器都会根据请求得相关信息加密得到一个指纹信息,并且将指纹信息和set()集合中的指纹信息进行 比对,如果set()集合中已经存在这个数据,就不在将这个Request放入队列中;
    5.如果set()集合中没有存在这个加密后的数据,就将这个Request对象放入队列中,等待被调度。
    
    scrapy和scrapy-redis有什么区别?为什么选择redis数据库?
    1) scrapy是一个Python爬虫框架,爬取效率极高,具有高度定制性,但是不支持分布式。而scrapy-redis一套基于redis数据库、运行在scrapy框架之上的组件,可以让scrapy支持分布式策略,
    Slaver端共享Master端redis数据库里的item队列、请求队列和请求指纹集合。
    2) 为什么选择redis数据库,因为redis支持主从同步,而且数据都是缓存在内存中的,所以基于redis的分布式爬虫,对请求和数据的高频读取效率非常高。
    
    
    python中使用的垃圾回收机制:

    1. 引用计数

    引用计数法有其明显的优点,如高效、实现逻辑简单、具备实时性,一旦一个对象的引用计数归零,内存就直接释放了。不用像其他机制等到特定时机。将垃圾回收随机分配到运行的阶段,处理回收内存的时间分摊到了平时,正常程序的运行比较平稳。但是,引用计数也存在着一些缺点,
    通常的缺点有:
    逻辑简单,但实现有些麻烦。每个对象需要分配单独的空间来统计引用计数,这无形中加大的空间的负担,并且需要对引用计数进行维护,在维护的时候很容易会出错。
    在一些场景下,可能会比较慢。正常来说垃圾回收会比较平稳运行,但是当需要释放一个大的对象时,比如字典,需要对引用的所有对象循环嵌套调用,从而可能会花费比较长的时间。
    循环引用。这将是引用计数的致命伤,引用计数对此是无解的,因此必须要使用其它的垃圾回收算法对其进行补充。
    也就是说,Python 的垃圾回收机制,很大一部分是为了处理可能产生的循环引用,是对引用计数的补充。

    2. 标记清除 解决循环引用的问题

    Python采用了“标记-清除”(Mark and Sweep)算法,解决容器对象可能产生的循环引用问题。(注意,只有容器对象才会产生循环引用的情况,比如列表、字典、用户自定义类的对象、元组等。而像数字,字符串这类简单类型不会出现循环引用。作为一种优化策略,对于只包含简单类型的元组也不在标记清除算法的考虑之列)

    跟其名称一样,该算法在进行垃圾回收时分成了两步,分别是:

    A)标记阶段,遍历所有的对象,如果是可达的(reachable),也就是还有对象引用它,那么就标记该对象为可达;
    B)清除阶段,再次遍历对象,如果发现某个对象没有标记为可达,则就将其回收。

    3. 隔代回收

    在循环引用对象的回收中,整个应用程序会被暂停,为了减少应用程序暂停的时间,Python 通过“分代回收”(Generational Collection)以空间换时间的方法提高垃圾回收效率。

    分代回收是基于这样的一个统计事实,对于程序,存在一定比例的内存块的生存周期比较短;而剩下的内存块,生存周期会比较长,甚至会从程序开始一直持续到程序结束。生存期较短对象的比例通常在 80%~90% 之间,这种思想简单点说就是:对象存在时间越长,越可能不是垃圾,应该越少去收集。这样在执行标记-清除算法时可以有效减小遍历的对象数,从而提高垃圾回收的速度。

    python gc给对象定义了三种世代(0,1,2),每一个新生对象在generation zero中,如果它在一轮gc扫描中活了下来,那么它将被移至generation one,在那里他将较少的被扫描,如果它又活过了一轮gc,它又将被移至generation two,在那里它被扫描的次数将会更少。

    gc的扫描在什么时候会被触发呢?答案是当某一世代中被分配的对象与被释放的对象之差达到某一阈值的时候,就会触发gc对某一世代的扫描。值得注意的是当某一世代的扫描被触发的时候,比该世代年轻的世代也会被扫描。也就是说如果世代2的gc扫描被触发了,那么世代0,世代1也将被扫描,如果世代1的gc扫描被触发,世代0也会被扫描。

    反爬对抗
    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生成的。首先用Firebug或者HttpFox对网络请求进行分析。如果能够找到ajax请求,也能分析出具体的参数和响应的具体含义,我们就能采用上面的方法,直接利用requests或者urllib2模拟ajax请求,对响应的json进行分析得到需要的数据。

    4. js加密
      需要破解网页上的js加密过程,代码实现 或者 直接执行该段js代码

    5. cookies 反爬
      一些网站会有cookie反爬,cookie有时效性。可以通过多账号模拟登陆,拿到cookie,维护一个cookie池。

    6. app逆向
      需要反编译apk文件,hook到加密位置, 找到加密代码。

    7. app加壳
      需要进行脱壳处理,然后在进行APP逆向操作

    8. so文件加密
      so文件为动态加载的文件,libnative-lib.so中,函数只有调用中才会加载,加密是找到函数偏移和长度,进行位运算,所以解密也就按照一样的方式还原即可。

    TensorFlow 是由 Google Brain 团队为深度神经网络(DNN)开发的功能强大的开源软件库

    TensorFlow 则还有更多的特点,如下:
    支持所有流行语言,如 Python、C++、Java、R和Go。
    可以在多种平台上工作,甚至是移动平台和分布式平台。
    它受到所有云服务(AWS、Google和Azure)的支持。
    Keras——高级神经网络 API,已经与 TensorFlow 整合。
    与 Torch/Theano 比较,TensorFlow 拥有更好的计算图表可视化。
    允许模型部署到工业生产中,并且容易使用。
    有非常好的社区支持。
    TensorFlow 不仅仅是一个软件库,它是一套包括 TensorFlow,TensorBoard 和   TensorServing 的软件。
    
    分布式锁要满足哪些要求呢? 保证大家访问这个资源数据是一致性
    排他性:在同一时间只会有一个客户端能获取到锁,其它客户端无法同时获取
    
    避免死锁:这把锁在一段有限的时间之后,一定会被释放(正常释放或异常释放)
    
    高可用:获取或释放锁的机制必须高可用且性能佳
    
    基于 数据库实现 redis 基于Redis实现的锁机制,主要是依赖redis自身的原子操作
    乐观锁
     (1)锁服务要有递增的版本号version
     (2)每次更新数据的时候都必须先判断版本号对不对,然后再写入新的版本号
     (需要注意的是,在InnoDB中只有字段加了索引的,才会是行级锁,否者是表级锁,所以这个id字段要加索引)
    
    mysql 悲观锁 当这条记录加上排它锁之后,其它线程是无法操作这条记录的。

    基于 ZooKeeper实现 是一个分布式的、开源的程序协调服务,是 hadoop 项目下的一 个子项目 他提供的主要功能包括:配置管理、名字服务、分布式锁、集群管理。 就是使用它的临时有序节点来实现的分布式锁。
    当某客户端要进行逻辑的加锁时,就在zookeeper上的某个指定节点的目录下,去生成一个唯一的临时有序节点, 然后判断自己是否是这些有序节点中序号最小的一个,如果是,则算是获取了锁。如果不是,则说明没有获取到锁,那么就需要在序列中找到比自己小的那个节点,并对其调用exist()方法,对其注册事件监听,当监听到这个节点被删除了,那就再去判断一次自己当初创建的节点是否变成了序列中最小的。如果是,则获取锁,如果不是,则重复上述步骤。

    app 双向认证

    关于双向证书认证:客户端有自己的密匙,并持有服务端的证书,服务端给客户端发送数据时,需要将服务端的证书发给客户端验证,验证通过才运行发送数据,
    同样,客户端请求服务器数据时,也需要将自己的证书发给服务端验证,通过才允许执行请求。

    创建一个证书的步骤:

    (1)生成系统私钥
    (2)生成待签名证书
    (3)生成x509证书, 用CA私钥进行签名
    

    InnoDB MyISAM

    事务处理或是外键 全文索引

    大尺寸的数据集趋向于选择InnoDB方式,支持事务处理和故障恢复。数据库的大小决定了故障恢复的时间长短,InnoDB可以利用事务日志进行数据恢复,这会比较快。
    而MyISAM可能会需要几个小时甚至几天来干这些事,InnoDB只需要几分钟。

    总结:InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁。

    多进程、多线程、协程

    多进程:密集CPU任务,需要充分使用多核CPU资源(服务器,大量的并行计算)的时候,用多进程。 multiprocessing
    缺陷:多个进程之间通信成本高,切换开销大。
    
    
    多线程:密集I/O任务(网络I/O,磁盘I/O,数据库I/O)使用多线程合适。
    threading.Thread、multiprocessing.dummy
    缺陷:同一个时间切片只能运行一个线程,不能做到高并行,但是可以做到高并发。
    
    Python的多线程:
    
    GIL 全局解释器锁:线程的执行权限,在Python的进程里只有一个GIL。
    
    一个线程需要执行任务,必须获取GIL。
    
    好处:直接杜绝了多个线程访问内存空间的安全问题。
    坏处:Python的多线程不是真正多线程,不能充分利用多核CPU的资源。
    
    但是,在I/O阻塞的时候,解释器会释放GIL。
    
    协程:又称微线程,在单线程上执行多个任务,用函数切换,开销极小。不通过操作系统调度,没有进程、线程的切换开销。genvent,monkey.patchall
    
    多线程请求返回是无序的,那个线程有数据返回就处理那个线程,而协程返回的数据是有序的。
    
    缺陷:单线程执行,处理密集CPU和本地磁盘IO的时候,性能较低。处理网络I/O性能还是比较高.
    

    sort 与 sorted 区别:

    sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
    
    list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
    

    filter、map

    def func(i):
        return i % 2 == 1
    
    newlist = filter(func, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])   # filter 过滤
    newlist1 = filter(lambda i: i % 2 == 1, a)
    print(list(newlist))
    print(list(newlist1))
    
    r = map(lambda x: x ** 2, [1, 2, 3, 4, 5])     #  会根据提供的函数对指定序列做映射。
    print(list(r))
    

    mysql 事务

    mysql  事务是由一组SQL语句组成的逻辑处理单元,事务具有ACID属性。
    事务 :是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合
    原子性(Atomicity):事务是一个原子操作单元。在当时原子是不可分割的最小元素,其对数据的修改,要么全部成功,要么全部都不成功。
    
    一致性(Consistent):事务开始到结束的时间段内,数据都必须保持一致状态。
    
    隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的”独立”环境执行。
    
    持久性(Durable):事务完成后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。sx
    

    触发器

      触发器是一种特殊的存储过程,主要是通过事件来触发而被执行的,他可以强化约束,来维护数据库的完整性和一致性,可以跟踪数据内的操作从而不允许未经许可的                 更新和变化,可以联级运算。只有表支持触发器,视图不支持触发器
    

    1、给手机安装软件
    离线
    将init_machine.sh,及android_package.zip上传至/data/local/tmp目录下
    给手机安装termux,此为命令行工具,打开软件
    输入su,切换至管理员账户
    输入cd data/local/tmp,因为云手机不能打/符,所以用tab键来凑齐。
    输入sh init_machine.sh,即可安装好软件和服务
    usb线连
    在电脑上输入python -m uiautomator2 init即可
    2、打开ATX
    打开ATX 点击"启动uiautomator"

    3、打开QpythonL
    一定要先打开这个软件,不然你python脚本会上传不成功,

    打开软件后的顺序为:
        文件
        scripts
    

    4、上传脚本
    将auto_test.py和wx_helper.py上传至/storage/emulated/0/qpython/scripts文件夹下

    5、运行脚本
    打开QpythonL点击auto_test.py文件,点击下方的三角符号

    Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。

    sekiro

    sekiro是一个基于长链接和代码注入的Android private API暴露框架。
    
    框架分为两部分:
    
    server
    暴露一个TCP端口和两个HTTP端口
    管理通过TCP连接的client和user发来的http 请求
    client
    通过TCP和server连接,响应server发来的请求
    工作流程是这样的:
    
    client通过TCP和server建立长连接
    user发送http请求给server
    server根据用户发来的http请求的参数,通过TCP将请求转发给client
    client收到请求并响应server
    server将从client收到的请求返回给user
    
    

    相关文章

      网友评论

          本文标题:python爬虫 面试常见问题

          本文链接:https://www.haomeiwen.com/subject/cvabwktx.html