爬虫最基本的结构和流程:调度、下载、抽取、入库
01 IP被封
爬虫初学者最常遇到的问题是IP被封;
原因很简单,在抓取信息时,一没有隐藏自己实际IP,二访问频率太快,给对方服务器造成压力。
-
代理IP
-
控制对同一站点的访问频率(要么让它sleep、要么让它抓别的站点)
最直接的解决办法是使用大量代理IP,保证IP被封时有替换IP可用。
02 容易被反爬kill?
Headers
通过设置headers将爬虫伪装成浏览器,现在大部分的网站不这样伪装一下根本爬不了。
headers = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
}
一般headers设置user-Agent即可,如果有的数据
是登陆后才能看到的话,还需要添加cookies参数
先登陆账号后,在浏览器的开发者工具中,拷贝
Cookies即可。
提问:如果不想让Cookie中携带自身账号内容怎么办?
答:可以利用浏览器的无痕窗口功能,进入网页再取Cookie即可。
这些参数都可以在浏览器的开发者工具中找到,知乎示例:
注意:如果要分享代码给别人的话,代码中的 cookie 数据一定要删掉,否则别人可以通过这个直接免密登陆你的账户。
需要登录?
对于需要登录的一般有以下几种处理方法:
-
直接模拟登录后的动作,利用cookie、携带用户信息等方式发起请求,绕过登录动作
-
机器人自动登录
-
直接使用webkit和js去操作登录
主要说一下前两种,工具:firefox+httpfox;
机器人自动登录:原理很简单,就是程序post_data真实用户信息发起请求。
至于最后能不能成功登录且获取登录后的信息,个人经验觉得看对方校验严格程度。
有些网站post_data有一些乱七八糟的数据值,无法分析清楚,虽然携带真实用户信息请求,但总是返回用户名和密码不一致,而有的简单就容易攻破。
03 请求出错?
1)爬取页面开始没有问题,爬到某个时刻异常报错?
如果是403错误,是被反爬抓到了。
解决方法:
-
设置headers,建一个user-agent池,每次用不同到user-agent访问,用来模拟不同浏览器访问页面
-
设置代理池,每次用不同的ip
-
设置延迟,time.sleep(random.randint(0,5)),改变抓取效率,防止被发现
2)ConnectionResetError问题
重连失败,看看header里面是不是Conection是不是设置的keep-alive,改成close。
3)ssl证书验证问题
如果有证书,就写上,没有就设置ssl为False(使用不同的库设置方法不一样,协程中是在请求里加上verify_ssl=False,requests是在请求里加上verify=False)
4)访问时间过长造成假死
设置timeout,在请求里加上timeout=10,防止请求时间太长使程序阻塞。
04 正则表达式不太会怎么办?
有些数据不能直接用,又需要提取关键数据,正则表达式不太会怎么办?
使用正则表达式处理字符串,用好了确实很厉害,但是门学起来麻烦还容易忘,对新手来说有点难度。
上面这种情况可以试试使用字符串自带的拼接 ,分割(split)等功能实现。
比如我获取到一个网址链接 html/2019-05/06 ,我需要从中提取出包含的年、月、日信息。
我可以这样:
url = 'html/2019-05/06'
# 先根据 / 分割,得到 group1
group1 = url.split('/')
# 分割完后,group1 = ["html","2019-05","06"]
day = group1[2] # day = "06"
# 将 group1[1],也就是 2019-05 进行分割,根据 - 分割成 group2
group2 = group1[1].split("-")
# 分割完成后,group2 = ["2019","05"]
year = group2[0] # year = "2019"
month = group2[1] # month = "05"
小小一个函数,用熟练后,还是能做不少事情的。
05 爬到的数据乱码问题
一般大家看到乱码,可能会觉得是代码有问题爬错东西了。其实不然,是编码的问题,解决方式也很简单。
程序中涉及到编码格式的地方有两处:一处是在发起请求后,对返回的内容进行解码;另一处是在保存文件时,设置编码格式。
分别来看看:
1)发起请求,获取网页内容阶段
一般的网站的编码格式都是 UTF-8,你系统的默认编码也是 UTF-8 时,也就是说你的默认编码方式和目标网站的编码方式一致时,即使不明确设置编码方式,也不会出问题。
但如果不一致,就会出现乱码,这也是为什么经常有 “明明在我电脑上运行是好的,为什么在你电脑上就乱码了” 这样的问题。
这种问题解决也很简单,只要在代码中设置一下 encoding 即可。
这里介绍一种方法:r.encoding = r.apparent_encoding
这个可以自动推测目标网站的编码格式,省的你自己去一个个设置(当然极少数情况下它可能会推测错误出现乱码,到时候你再手动去查看网页编码,手动设置吧)。
def fetchURL(url):
headers = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
}
r = requests.get(url,headers=headers)
r.raise_for_status()
# 这里设置编码格式
r.encoding = r.apparent_encoding
return r.text
2)保存文件时的编码错误
爬取过程中没问题,但是用 excel 打开保存好的 csv 文件时出现乱码(用记事本打开没问题)。
这个其实就是文件的编码方式和 Excel 的解码方式不一致导致的;
在 dataframe.to_csv 这句,参数里添加一个 encoding=‘utf_8_sig’,指定文件的编码格式,应该就可以解决了。
def writePage(urating):
'''
Function : To write the content of html into a local file
'''
import pandas as pd
dataframe = pd.DataFrame(urating)
dataframe.to_csv('filename.csv',encoding='utf_8_sig', mode='a', index=False, sep=',', header=False )
之前乱码的 csv 文件,可以用记事本打开,然后
点另存为,然后选择编码格式,ANSI ,unicode,
UTF-8 都可以,然后保存之后,再次用 excel
打开就是正常的了。
如果你不知道你的乱码是哪种问题,有一个简单的判断方法:
用记事本打开 csv 文件,如果正常显示,那么无误就是第二种情况,如果是乱码,那么很有可能是第一种情况。
保存文件这里补充一个问题:
- 为什么保存文件时候会报错 “FileNotFoundError:No such file or directory” ?
在保存文件时,如果路径下你要操作的文件不存在,它会自动创建一个文件,然后写入数据。
但是,如果是路径中的文件夹不存在,则不会自动创建,而是会报错。
以后看到这样的错误,不要慌,只是你的路径中没有对应的文件夹而已,缺哪个文件夹,自己手动创建好,再运行就好啦。
如果你想让代码自动创建文件夹,也很简单,只需要在保存文件前,执行这些代码即可。
import os
# 如果没有该文件夹,则自动生成
if not os.path.exists(path):
os.makedirs(path)
06 整理的相关报错问题
1)类型错误:需要类似字节的对象,而不是字符串?
解决方案:str通过encode()方法可以编码为指定的bytes;
反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes,要把bytes变为str,就需要用decode()方法。
2)UTF-8不能处理字节?
解决方法:在headers中加入Cookie即可输出正常的HTML。
3)‘ gbk ’不能处理‘ \xa0 ’ ?
解决思路:
with open('%s.html' % title, 'w', encoding='utf-8') as f:
f.write(rep)
4)输出结果是字节类型,json对象无法正常显示?
解决:使用json.loads方法即可;
5)网址复制到py文件中,却变成了“乱码”?
url = ‘https://tieba.baidu.com/f?kw=%E8%8B%B1%E9%9B%84%E8%81%94%E7%9B%9F&ie=utf-8&pn=0’
解决方法:调用urllib.parse.unquote进行URL解码;
6)显示URL地址不规范?
分析URL时,我们一般从第二页开始分析,而不是第一页。
7)其他报错消息
① syntaxerror: invalid syntax语法错误:无效语法
② syntaxerror: unexpected EOF while parsing语法错误
多了无法解析的符号(检查是否多了或少了括号)③ syntaxerror: invalid character in identifier语法错误
有无效标识符(检查中文符号)④ indexerror: list index out of range索引错误
列表超出索引范围(检查列表是否为空)⑤ typeerror: must be str, not int类型错误
数据不是正确的数据类型,比如字符串和数字直接拼接(检查数据类型)⑥ indentationerror: expected an indented block缩进错误
检查代码的缩进是否正确⑦ valueerror: substring not found值错误
输入的数据类型跟要求不符合⑧ nameerror: name ‘a’ is not defined未初始化对象,变量没有被定义
⑨ attributeerror: ‘tuple’ object has no attribute 'remove’属性错误
该对象没有这个属性、方法(检查数据类型)
07 抽取失败怎么查?
检查下载回本地内容
是否下载完全?下载是否正确(即是否是自己想要的内容)?是否包含所要抽的内容?
有的时候因为以下这几点原因:
-
网络原因,它会下载不全;
-
由于封禁等原因会导致下载非所要内容,甚至会被通知“机器人检查”;
-
Js加载等浏览器本地处理,导致你在页面能看到,并不代表你已经下载回所看到的内容了
其实web,网页文本是一部分,会随着当次请求返回,而其余的类似css\js\图片等等。
第一次获取到的只是url等信息,也就是说我们从浏览器看到的一次请求实际上是包含了n次请求的,或前或后最后统一由浏览器加载呈现。
检查xpath是否正确
当然也可以是其他的定位方法,这里拿xpath举例,xpath是否准确定位到所需信息?
还有一个问题:如果正确使用xpath之后并没有输出呢?
解决:xpath只能提取未注释的代码,改用正则表达式即可。
检查提取方法是否正确
可以用正则,也可以用python自带的字符串处理函数,这个看你喜欢,但貌似正则看起来更美观些。
遇到过的情况:信息藏在利用工具获取的xpath节点的父节点、信息做了简单防抓取截断甚至js等处理……
这些情况可以仔细分析网页源码加以针对解决,只要到了本地,有就一定能抽出来。
图片抽取失败
首先看是否进行了全局抽取,有的为了防止抓到广告图片,限定了抽取范围,而一旦对方变了模板,此时的图片抽取会失效。
其次就是程序逻辑了,是否进行了次数限制,比如前边弄了10张,就不去扫描下面的内容了。
08 封禁之外的常见信息保护措施
信息图片化
这样即使你抓到该图片,要想获取信息,也得费一番劲了。
常见的比如价格图片、电话图片、验证码等等,而作为抓取方,这就得依赖后端服务了,比如图片识别ocr。
有意信息截断分开存储
拿电话图片举例,比如前三位存一个地方,后八位显示星号,用户通过点击button获取完整的电话号码,其实这纯粹是个防傻瓜机器人的trick,你要想复杂的做可以模拟js点击,再获取。
但更简单的方法是分析其网页源码,找到分散的部分,直接正则分别提取,再拼接即可。
对非登录用户不展示
这个的话,临时抓取可以利用破解登录的方法,但是别人想kill掉你也是很容易的,因为你短时间内同一账号大规模的访问,这个是非常容易被发现的,除非对方压根不想管你。
不然就是你有成千上万个马甲,你要搞到这种程度,我也只能拜服了。
比如12306要想封插件,肯定不是问题,很简单啊,你一个账号10、20分钟刷一次,避免误判,我忍了,可你连续几小时这样,封你就不用说了。
结语:爬虫原则
最后再说一下爬虫的一些原则
① 指定爬取策略时,尽可能少的发起网络请求。一次请求能解决的事儿,尽量不要多次。
② 控制发起请求的频率,过于频繁的访问,不仅给对方服务器带来压力,也容易被对方反爬虫系统针对。
③写爬虫要有敬畏之心,切忌不当使用爬虫!
爬虫毕竟只是工具,是手段,真正重要的东西是数据,所以,不要为了使用爬虫而使用爬虫,数据量较小,能手动解决的尽量手动解决。
关于Python学习指南
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。我收藏了很多技术干货,可以共享给喜欢我文章的朋友们,如果你肯花时间沉下心去学习,它们一定能帮到你,干货内容包括:
👉Python所有方向的学习路线👈
Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
👉Python学习开发工具👈
工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。
👉Python入门学习视频👈
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。
👉Python实战练手案例&源码👈
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
👉全套PDF电子书👈
书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。
👉Python大厂面试资料👈
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
👉Python副业兼职学习路线👈
👉 这份完整版的Python全套学习资料已经上传,朋友们如果需要可以扫描下方优快云官方认证二维码或者点击链接免费领取【保证100%免费
】
读者福利:优快云大礼包:《Python小白从入门到精通全套学习资料》免费分享 安全链接免费领取
