爬虫最基本的结构和流程:调度、下载、抽取、入库
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全套学习资料已经上传,朋友们如果需要可以扫描下方CSDN官方认证二维码或者点击链接免费领取【保证100%免费
】
读者福利:CSDN大礼包:《Python小白从入门到精通全套学习资料》免费分享 安全链接免费领取
![](https://i-blog.csdnimg.cn/blog_migrate/89bfd170e0c32520eedf0d4ca18f9145.jpeg)