是的,我改了博客名,不知道为什么要改,就感觉现在这个名字看起来要洋气一点。
最近有点空余就一直在开发我的项目,最近做了两个项目:
根据以上爬取的大概也许可能接近上百个网站吧,加上我初学爬虫的时候爬的网站,现在也算是爬了有接近上千个网站了,对爬虫也算是小有心得了,下面就开始说说吧
最近时不时总是冒出一两个因为爬虫入狱的新闻
不一一截图了,自己网上搜吧,其实现在越来越多了
上面说了,有通用爬虫和聚焦爬虫
通用爬虫:
针对于百度,搜狗,谷歌这类搜索引擎类的爬虫程序
聚焦爬虫:
又名定向爬虫,就是我们平时写的针对某个需求或者某个问题而写的程序
一句话,所见即所得,什么意思,你用浏览器能访问,能查看的网页数据,用爬虫就可以爬到,反过来,你浏览器都无法访问的,爬虫是无法爬到的,除非你用一些违法的手段获取到
举个例子:
我知道有一部分圈子里的朋友之间流传着有什么破解vip之类的,那种其实也是符合所见所得的,你没有vip,别人有啊,假如一个已有vip账号的人把视频下载下来上传到云服务器A,然后你访问某个网站,网站后台请求的是云服务器A,最后呈现视频数据给你,不说了,扯远了
分类看以什么分了,有自动的,有手动的,有在线的,有离线的,有傻瓜式的,有非傻瓜式的,有分析辅助为主的,有自开发式的,看每个人怎么定义了
比如什么八爪鱼,爬山虎,啥啥的一大堆,在线的傻瓜式的工具,根据提示点点鼠标,输入几个字就完了,但是这种工具普遍得到的结果不是很理想
以下的都是作为辅助分析整个请求过程的工具
而需要点技术的就是自开发式的,比如自己借助某个开发语言写爬虫程序(或者说脚本)就是了
其实还挺多的
php写爬虫是可以的,但是多线程多进程不太支持,所以针对大型一点的项目不够理想
nodejs的curl工具也是可以写爬虫的,有什么优缺点我暂时不知道,我没用过
java的话,听大佬说的,写出来的爬虫程序很臃肿,不是说不好哈,我暂时只是有耳闻,没用过
golang天生支持高并发,性能提升很多,也可以做爬虫,这个我暂时只是有耳闻,没用过
python的话写爬虫真的是一种神器般的存在,目前网上的爬虫程序,可能百分之八九十都是用Python写的
其他语言只要支持网络服务应该都可以写爬虫,这里就不多说了
自带的库:
python2下:
python3下:
第三方的库:
目前就想到这么多
平常的话,做网络交互我就用requests库,但是有些小问题,用多了的人应该都知道,requests库里的异常类不够全,有时候报错了无法捕获
做数据解析的话我用json,re,lxml,beautifulsoup,pyquery,execjs,js2py都有在用,只要有场景需要就会用
大型项目就上scrapy,需要分布式就上scrapy-redis
重头戏终于来了,哈哈,我也有点按奈不住了
这个稍微接触过一点点爬虫的应该都不陌生,不是说接触Python爬虫,不管你用什么开发语言来写爬虫,应该都会用到这个。大概解释一下,就是一个身份的象征,这个可以用浏览器自带的调试工具查看,访问一个网站的时候,按f12键或者鼠标右键打开调试(有的浏览器叫检查,或者查看元素),然后切换到network(网络),重新刷新一次网站,就会出现所有的请求,随机点击一个,右边出现的就是请求头信息了,如下,这是我访问某某网站的,我使用的浏览器是火狐,然后图上标注的就是user-agent
具体怎么用呢?
比如:
这样就可以带上UA了
如果不带的话,你的目标网站服务端是可以检测到是浏览器还是爬虫工具在访问数据的,就看你的目标网站的友好度了,如果反爬机制做的很高效,到这里你就被ban了
很多时候我们为了查看网页的DOM结构可能就直接用浏览器自带的调试工具(就是上面说的按f12键)来查看,这个的话,大部分网页是可以应对的,但是,少部分网站用调试工具查看的DOM结构和整个网页的源码是不一致的,说个最近的事,我爬某视频网站,调试工具打开他在每个重要信息都加了一个css样式,这个css样式是通过定位某个html标签(假设为标签)设置上的,我解析网页的时候就很痛苦,调了很久,就是得不到结果,最后发现这个span标签是用js拼接上的,换句话说,服务端回应的是不带有这个span标签的,所以就要没有这个span标签来处理。说这么多不知道看官您能不能理解,遇到过这个问题的朋友应该明白我在说什么
上面说的DOM结构不一致还有一种可能,就是前后端用的Ajax异步请求的,所以你打开浏览器的调试工具查看DOM结构和你用Python获取的结果也是不一致的,这个相信会玩爬虫的老哥们都不陌生
有一部分网站,当你访问首页时,会自动设置一个cookie,然后访问同站下的其他页面就会验证这个字段,如果不匹配就会禁止访问
如下,访问百度都会自动设置一些cookie:
特殊字段是什么呢,就是某网站特有的一些字段,比如以下的boss直聘网:
会带有这些特殊的字段。当然这里只是举个例子,,经过我的测试,我圈出来的那几个[:method]等的字段其实请求的时候是不用带上的
这个referer是干嘛的呢?首先该字段的值都是上一级网站的url,根据我的理解,它有以下作用:
1.做前端的朋友知道,可以借用这个字段直接返回到上个页面
有的网站就是因为有这个验证,所以返回的数据不正常,带上就OK了。还有的网站更奇怪,你不带上也不会报错,返回的数据也是希望的数据,但是无法和页码匹配,比如你请求的是第一页的数据,它有可能返回的是第5页的数据。遇到过这个问题的老哥应该知道我在说什么
不知道老哥您遇到过这个问题没有,在请求头里,如果服务端返回的结果是普通的html页面的话,值就应该是如下的:
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',如果返回的是json字符串(返回json字符串的话,往往是属于异步请求)的话,值就应该是这个:
'Accept':'application/json,text/javascript,*/*;q=0.01',
这个不知道你们有没有体会,反正我记得我爬某网站的时候,因为都通用的同一个请求头,有的网站就是返回json数据,我怎么改代码都无法得到正确的值,就是因为本来是json字符串的我的accept用的上面的html页面用的,导致返回数据不符合事实。
这个问题的话,在一般情况下还是不会遇到,主要就是在高并发请求的时候,有可能同一个时刻请求多次来自同一个站点的数据,触发该网站的反爬机制的频率限制,就会出现什么scoket.timeout,urllib3.connection.HTTPConnection之类的错误。所以从那次之后我的爬虫程序如果用了高并发的话,我都会把这个connection设置为close
gzip的意思就是这个网站的数据是做呀gzip压缩的,在浏览器(客户端)访问之后,会自动处理这类格式的数据。但是使用Python的标准款urllib的话,是不会处理这类格式的,解决方法就是用requests库,会自动处理gzip格式,反正这个库真的太强大了
当然这个问题也不是一定会遇到,有时候只是某个其他的异常爆出,导致后续的代码跟着出错,然后跟着抛出异常,所以也不能盲目的用异常基类来捕获
这个token在语义上就是个令牌的意思,用的比较多的地方就是在手机端上用token验证,此手机端的验证对应的电脑端用的session验证,而电脑端用token的情况就是,特殊字段的变异,有的网站就放在请求头的authorized键里,值就是token,用uuid生成的,有的就是自定义的键,比如boss直聘的就是__zp_stoken__,必须要带上这个字段才能爬取(因为boss直聘的反爬机制升级了,以前直接可以爬,现在必须带上这个字段才行,说句题外话,目前我还没找到boss直聘这个字段是怎么生成的,用fiddler抓包发现请求了阿里云的服务端,但是返回的数据是空,反正没找到它是怎么生产的)
一般情况下,电脑能访问的页面,手机一定能访问,只是如果该站没有作响应式的话,用手机访问的页面排版很乱,因为手机和电脑的尺寸不一样嘛。
这种网站怎么爬取呢,requests会自动处理重定向的问题,没错,requests就是这么抗打
什么意思呢,就是比如我在某一个网站点一下按钮,触发机制,用新的网页标签打开的,前端的朋友应该知道,就是a标签属性里加了个target='_blank',这种的话,如果用浏览器的调试工具来分析的话就无法即时的查看请求了。因为习惯上我喜欢用浏览器自带的调试工具分析,比较方便快捷,实在不行的话就上fiddler啥的抓包工具。没错,解决方法我已经说了,像这种点击一个会以新的浏览器窗口打开的就用抓包工具来分析
这个我不知道你们遇到过没,我有一次抓某个网站,它就是为了防止我这类瞎jb搞的人分析它的代码,分析它的请求过程,所以当我一打开调试工具,就触发它的监听器,然后我就发现我电脑的CPU立马跑满了,一直在消耗我的电脑资源直到电脑卡死,所以我只能感觉关闭调试工具或者关闭浏览器,实在不行只能重启了,它就是监听的debuger,我不知道这个是一个函数还是一个类,以下是我保存的代码,看有缘人能不能看懂,看懂的话我就以身相....,不对,走错片场了,卧槽。。。
varcheck=(function(){varcallbacks=[],timeLimit=50,open=false;setInterval(loop,1);return{addListener:function(fn){callbacks.push(fn);},cancleListenr:function(fn){callbacks=callbacks.filter(function(v){returnv!==fn;});}}functionloop(){varstartTime=newDate();debugger;if(newDate()-startTime>timeLimit){if(!open){callbacks.forEach(function(fn){fn.call(null);});}open=true;window.stop();}else{open=false;}}})();
针对该站,我只提供大概思路,就是第一次请求获取js,用js库(execjs或者js2py)执行这段Js获取到cookie,将cookie留下,第二次带上这个cookie去请求即可,两次请求使用的UA必须是同一个即可,
有的时候如果要传递参数到服务端的话,那么就得做url编码,使用url编码解码就可以用urllIb.parse.quote和urlib.parse.unquote,使用quote方法作编码的话,默认使用的是utf-8的编码,但有时候一些网站用的gbk,所以这是一个坑,你得用quote(kw,encoding='gbk')才能转为gbk的编码,不熟悉这个的话就很难发现这个,因为我们一般就直接用quote就行了,根本不在意是用了什么编码
不多说了,requests做post请求时,提交的data字段会默认将data字段作url编码,且默认用的utf-8编码,对的,又是编码的锅,而有的网站用的并不是utf-8编码的,假如某网站用的是gbk编码,如果我们还是默认的操作的话,就会出错,解决办法就是,手动编码:
解析网页结构的工具很多,比如一大杀气正则表达式,然后就是xpath,再然后就是bs4,最近我痴迷于xpath,我觉得写起来异常的顺畅,非常有感觉,但是在其中还是遇到了问题如下,无法解析带有tbody标签,这个是我最近发现的,不知道是不是版本问题,只要网页的DOM结构用tbody,比如标签下有tbody/tr/td时,我要取td下的数据,按理就是写的response.xpath('//table/tbody/tr/td/text()'),但是这样写有时候就是的拿不到,得去掉tbody,写成这样就可以拿到:response.xpath('//table/tr/td/text()')
原因你可以看下网站源码,有很多网站的源码是table下就直接写tr标签,然后浏览器渲染的时候自动把tbody补上了,所以你写response.xpath('//table/tbody/tr/td/text()')就会拿不到数据,这只是举个例子,在解析网站的时候注意看源码,很多时候你用审查元素看到的跟实际的源码其实是不一样的,尤其是ajax动态加载的数据
一般情况下,我们获取某个数据的话,直接就根据class属性或者id属性,反正就一些非常特定的属性三两下就可以定位元素,但是有的元素就是什么属性都没带的,就只是一个标签名,而且这个标签用的还异常的多,此时此刻的话,你就可以你的目标元素就近的标签有没有很特殊的属性,直接就可以定位的,然后用following-sibling定位兄弟元素即可,比如:following-sibling::span[1]/text(),补充一个:回到上级:用【..】表示回到上级,再补充一个,用contains(text(),'xxx'):根据一个元素的内容包含某个字段来定位
当然这几个都是很简单的,这个本来就是xpath的基础部分,但是我跟你说,这三个配套使用的话就没有锁定不了的元素,通通一杀一个准,真的,我感觉用多了xpath,比用beautifulsoup还顺手
简单验证码,比如一些肉眼很好看出的验证码的话,可以借用tesseract库来识别,做ocr提取,比如以下就是我那个IPproxy里的某一段代码:
直接就可以把简单的验证码的数据提取出来,更多的操作就不说了,网上一大堆
滑动验证码的话,以极验的滑动验证码为典型,之前网上有一大堆的极验验证码破解,不过都是2.0的破解,更新到3.0之后,破解的人就少了,不过,嘿嘿,我还是破解了,
网易系的就不多说了,坊间传闻的,网易的滑动验证码本来就是抄袭极验的(不是我说的),所以破解方法差不多,感兴趣的可以根据我的代码自行修改
有的网站比较大型,每天的访问量很大,那么这个网站对访问频率的限制就没那么严格,如果是小网站限制就会严一点,当然凡是无绝对,这个真的就看你的感知了,你如果感觉按你的代码运行下去可能爬不了几个数据就请求超时了,多半是触发访问频率的峰值了。如何解决,就只能看你自己怎么优化代码,保证代码每次请求的都不走空了,这个就没法具体的说了,你可以用协程来回的切换啥啥的
提升性能的话,要说的还挺多的,我就说几个比较典型的,如果你发现你的代码运行是串行的,你可以用gevent协程做切换,或者用线程池,或者用线程池+异步的方法,然后网络请求属于IO操作,所以不适合上多进程的方式
还觉得不够快,可以再用上解释器来直接解释这段代码,比如win平台下,直接用cpython对你的代码进行处理,其他平台的就用其他平台的解释器了,不多说了
还觉得不够快,技术再强点的话,可以写原生的C代码,把几个关键的操作抽离出来,用C来重构,然后运行的使用直接调用这段C代码(python有直接运行C代码的库,很多,网上自行查询)
还觉得不够快,升级你的硬件配置了
还觉得不够快?卧槽,没完了是吧,已经这样了,还想怎么个优化法啊老铁?
好的,以上就是我遇到的问题,在这过程中,有可能会遇到一些非常奇葩的问题,你简直无从下手的,然后慢慢找原因,找为什么,这样发散式的,又学到了新的东西。通过爬虫,我也对Python有了新的理解,新的体悟,从问题中成长,得到提升还是不错的
1.使用python中的requests库时(目前版本v2.22),以下哪种说法不正确:
A.支持自定义请求中的headers顺序
B.支持不同域名使用不同代理
D.支持socks代理
2.一般来说,python的requests.get函数会对传入的url进行urlencode操作.但当如下代码中的keyword为哪个选项时,无法得到预期的结果:
A.'梁斌'
B.'C#入门经典'
C.'r&b'
D.'川上とも子'
3.如果进行大规模并发抓取(比如1000并发+,单核单进程),下面哪个python的库的效率最好的:
A.urllib
B.requests
4.使用Chromedevtools控制单个Chrome浏览器进行自动化操作时(原生chrome,且不使用插件的情况下),以下哪个说法正确的是:
A.不能控制Chrome中的多个窗口
B.不能抓取来自网络层的原始数据
C.不能动态切换Chrome的代理
D.不能禁止图片加载
5.以下对于Chromeheadless模式的描述中,哪个是错误的?
A.headless模式的User-Agent与普通(非headless)模式是不一样的
B.headless模式是有BOM和DOM的
C.headless模式是不支持Webassembly的
D.headless模式是支持鼠标点击事件的
6.下列那种加密方式能最大限度抵御彩虹表的爆破:
A.HMAC-MD5
B.MD5
C.MD4
D.SHA1
7.现在很多app采用了证书锁定sslpinning来防止中间人攻击,关于sslpinning下列说法错误的是:
A.sslpinning是将服务端证书打包内置到移动客户端中,HTTPS连接建立时与服务端返回的证书对比一致性,以确定这个连接的合法性
B.采用sslpinning的app,仍然可以直接使用mitmproxy,fiddler等抓包工具可获取到明文包
C.使用frida等工具绕过证书锁定后,抓包工具才能获取到明文HTTPS数据包
D.采用了sslpinning证书锁定的app,内置证书一般为自签名证书
8.以下对xposed的描述中,正确的是:
A.xposed是对内核中init进行修改,使其能够注入到任何进程中
B.xposed不能hooknative中的函数
C.xposed中的XposedBridge.jar会出现在任意apk进程的/proc/self/maps中
D.xposed并不支持AndroidOreo的版本
9.以下哪条语句能在frida中输出2019,Pet类定义如下:
publicclassPet{
privatestaticintkind=2019;
privatestaticintkind()
{
return9102;
}
A.console.log(Pet._kind);
B.console.log(Pet.kind);
C.console.log(Pet._kind.value);
D.console.log(Pet.kind.value);
10.关于app反调试下列说法错误的是:
A.app可以通过ptrace自身,来阻止调试器ptrace附加到app进程实现反调试
B.在对程序脱壳过程中,经常需要将/proc/pid/mem或者/proc/pid/maps下内存数据dump出来,可以使用inotify对文件进行监控,如果发现文件系统的的打开,读写,可能程序在被破解,就可以执行kill进程操作
C.通过遍历程序内存段是否存在断点指令,来判断程序是否正在被调试,是则kill进程
11.以下关于frida的使用哪项不正确?
A.java层的hook必须在java.perform中执行
B.java层同名函数的hook,可以通过不同参数数量来区分,而不用写overload
C.frida以spawn方式启动app可以hookapp在启动时就执行的函数
D.frida可以更改某个native函数的实现
12.下面通过IDA反汇编的arm指令,其中描述不正确的是?
.text:0000ED72MOVSR0,R0
.text:0000ED74POP{R0}
.text:0000ED76CMPR1,#0
.text:0000ED78BNEloc_ED84
.text:0000ED7APUSH{R0,R1,LR}
.text:0000ED7CBLsub_B2544
.text:0000ED80MOVSR6,R1
.text:0000ED82MOVSR0,R0
A.BL是带返回的跳转指令
B.0xED7C位置进行的跳转后LR寄存器的值为0xED81
C.sub_B2544是程序员定义的函数名,此处将调用sub_B2544函数
D.0xED78位置的指令含义是如果R1!=0则进行跳转
13.做爬虫难,还是做反爬难?
发表下您的看法,并简单阐述下原因(100字以内,开放式题目,没有对错,可自由发挥)。
1)下面哪种方式可以让爬虫合理、合法地抓取当日尽可能多的数据?
A.通过漏洞进入他人计算机系统,把数据库dump出来。
B.用大量低频关键词在目标站点上搜索,获得当日更全数据。
2)以下所列出的方法中,浏览器web数据抓取效率最高的方法是?
A.selenium+phantomjs
B.使用chrome或者chrome内核抓取
C.模拟web协议直接用wget或curl抓取
3)下面哪项是手机端抓取app数据相比web端的优势(多选):
A.手机端协议简单容易分析
B.手机端可以使用模拟点击
C.手机端就算出新版了旧版还是可以继续使用,不会立即停掉
D.通常来说,手机端抓取同样信息量的数据,下载量更低
4)下面哪些代理支持rawsocket连接(多选)?
A.HTTP代理
B.HTTPS代理
C.SOCKS4代理
D.SOCKS5代理
5)下面代码请求实际访问地址url是什么?
params={
"xxxx":"1234"
headers={
"Host":"www.test.cn",
"Accept-Encoding":"gzip,deflate",
"Connection":"Keep-Alive"
requests.get(url,params,headers=headers,allow_redirects=False,verify=False)
6)假如你要爬大量youtube视频的二进制内容,存储在本地,最佳的办法是?
A.Mysql数据库存储
B.Redis存储
C.Mongodb存储
D.文件系统
7)如果想爬自己手机应用上的HTTPS的数据,获得明文,下面哪个说法是正确的?
A.自己搭建一个HTTPS代理,让手机设置为这个代理,即可获得明文
B.任何HTTPS明文都是可以获取的
C.在PC上建立一个无线热点,让手机连这个热点,并使用Wireshare软件分析出HTTPS的明文数据
D.通过让手机系统信任根证书,使用Man-in-the-middle中间人攻击技术,就可以获取任何HTTPS明文
8)以下哪个功能chromedriver协议不支持?
A.注入js文件
B.模拟鼠标滑动
C.网络请求的响应式处理
D.同个实例可以同时操作多个页面
9)爬取数据过程中,哪个情况是最不可容忍的?
A.爬取的数据不完整,有部分数据遗失
B.爬取程序非法关闭,内存泄露
C.爬取的数据部分出错,手动修改
D.不同版本的数据合并在一起
10)爬虫开发不会涉及到的技术或者知识有?
A.tcp,udp传输协议
B.反汇编技术
C.数据库存储
D.音视频流解析
E.网络路由协议
F.以上都会涉及
1)如何获得大量IP资源(业界主流方法)
2)如何获得账号资源,如何进行大量账号登陆
3)抓取系统如何构建,如何可扩展
4)如何探测封杀阈值
5)如何将爬虫模拟成正常用户
6)每个模块使用到的最佳工具
7)其他系统杂项trick,如何流量均衡等等
1)爬虫为什么要做DNS缓存?
A:可以节约抓取带宽
C:减少下载数据大小
D:防止多次DNS请求被抓取目标网站封杀
2)Etag干什么用的?
A:防止重复图片download
C:提示web服务可以接受压缩数据
D:提示网页内容的标签信息
3)Transfer-Encoding为chunked时,会出现什么情况
A:通常没有Content-Type域
B:通常没有Content-Length域
C:网页数据不可能同时即是压缩数据又是chunked数据
D:数据结尾标记是:一个数值(表示总长度)\r\n\r\n
4)tcp最小数据载荷是多少字节(抛出协议头部)?theminimum"data"sizeofaTCPsegmentshouldbe?
A:6字节
B:20字节
C:24字节
D:不确定
5)当最后一个包比最小数据载荷还小时,TCP/IP协议如何处理是否结束?
A:在最后一个包的末尾填充特殊字符以表示数据结束
B:最开始协商的数据大小和已经接受的数据一致即可判断结束