基础爬虫最常见报错解析(学爬虫必看)

整理最常见的爬虫报错,学会自查报错、利用网络解决bug 是作为一个程序员最基本的能力。


常见的爬虫问题

(个人见解,一定通俗易懂)

Q:爬虫到底是什么?

A:百度百科:网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。 对初次接触的人来说有点抽象?简单理解就是:用代码模仿人打开浏览器、浏览网页、登录网站的一系列操作。写的代码就叫爬虫。

Q:为什么要模仿?

A:这就是核心原因了,当人浏览网页的时候,网站会发送很多数据到你的设备上供你浏览,爬虫就利用模仿浏览器来获取网站服务器发送过来的数据,然后用一定规则来筛选数据,得到我们想要的东西。

Q:网站发过来的到底是什么数据?

A:根据网址不同 数据类型也不一样。
你访问的是最常见的网站(https://www.shicimingju.com/book/xiyouji.html),response.text 就是网站的html源码;
如果是图片/视频等(https://pic.netbian.com/uploads/allimg/240527/181242-171680476234cb.jpg),response.text可能会乱码(不过这不重要,因为我们不需要它),response.content 才是最重要的我们需要的二进制数据;
而如果是接口(https://yiqifu.baidu.com/g/aqc/getDistrictAjax),response.text 很可能是json数据,也可能是html源码,要注意response有json()方法,可以将自己的json数据直接转换为python数据( res = response.json() ),但是只能在response.text是json数据的时候使用。

Q:爬虫和浏览器是什么关系?

A:可以简单理解为 爬虫是无界面的浏览器。因为我们并不需要观看网站,只关心爬虫能不能成功获取网站发送来的数据。

Q:爬虫和我的浏览器同时打开网站会冲突吗?

A:不会,刚刚说过爬虫是无界面的浏览器,就相当于另外一个浏览器了,它们相互之间是独立的。

Q:爬虫和我的浏览器是相互独立的,为什么要打开浏览器来写爬虫?

A:还是因为爬虫无界面。其实我们是可以只通过爬虫返回的源码来写代码的,就像下面的代码,通过打印网站源码,我们就可以只观察网站源码来写代码,但是不用想就知道这极其不方便呀。在浏览器里能直观看到页面内容、跳转链接、快速定位源码位置、源码排版也清晰规律,这不香吗?

import requests
# 网址
url = 'https://www.shicimingju.com/book/xiyouji.html'
# 构建请求头
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}
# get请求内容
response = requests.get(url=url, headers=headers)
# 设置编码格式
response.encoding = 'utf-8'
# 打印网站源码
print(response.text)

Q:既然都是浏览器,那爬虫和浏览器的内容也是一样咯?

A:不一定。爬虫终究只是模仿,反爬能力强的网站还是能根据各种细节检测出来真浏览器和爬虫的,因此服务器发送回来的数据也是不一样的。上个问题说用浏览器查看网站来写爬虫,但写完之后的爬虫运行的结果不一定与浏览器相同,就是因为爬虫可能会被反爬从而导致获取的网站源码不一样。因此这里有一个特别大的坑:很多新手写爬虫只会看着浏览器里的网站源码说:我查找的标签明明有,也写对了,为什么找不到?那为什么不想想爬虫获取的网站源码和浏览器里的网站源码真的一样吗?遇到这种情况就参考上个问题的代码,把爬虫的网站源码打印出来看,与浏览器对比一下是否一致。
请记住:爬虫的基础是爬虫获取到的数据,也就是 response.text 才是爬虫自己的源码!!!我们用浏览器只是为了方便写代码,不要把浏览器里的网站源码当成爬虫的源码!!!当网站没反爬时两者源码基本一致,有反爬时就不一样了!!!


常见爬虫报错

AttributeError: “NoneType” object has no attribute ‘text’

这是一个常见的报错,出现情景大概率是以下操作:爬取网页html源码 - BeautifulSoup解析 - 利用find查找标签 - 获取该标签的文本(text), 于是在获取文本时报错,报错信息为:NoneType(空类型) 对象没有text属性如果看不懂英文就去翻译,翻译软件又不收钱。当能够自己查错并修复时就代表你已经迈入初步的程序员了。

拓展:find 方法语法: find(name, attrs, recursive, text, **kwargs)

参数含义
name指定要查找的标签名,可以是字符串或正则表达式等。
attrs通过指定属性名和属性值的方式来查找元素。
recursive指定是否对子孙节点进行递归搜索,默认为True。
text通过指定文本内容来查找元素。
kwargs其他的一些属性和关键字参数。

报错解决思路(学习重点!!!)(以下面的代码为例):

from bs4 import BeautifulSoup
import requests
# 网址
url = 'https://www.shicimingju.com/book/xiyouji.html'
# 构建请求头
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}
# get请求内容
response = requests.get(url=url, headers=headers)
# 设置编码格式
response.encoding = 'utf-8'
# html解析
soup = BeautifulSoup(response.text, 'html.parser')
# 查找一个a标签:在这里我选择查找一个a标签,指定的属性名为 href,正确的属性值为 /book/xiyouji/1.html。
# 为了演示效果,我把属性值删掉一个 h,让 find 查找为空以便于演示。
res_tag = soup.find("a", href="/book/xiyouji/1.tml")
print(res_tag.text)
  1. 不论发生什么报错,第一时间最应该做的就是先查看报错,不懂英文就去翻译!
    在这里插入图片描述
颜色框含义
红框报错行提示,表示是第几行的代码报错了,红框前面的文件表示该报错行在哪个文件里面。这里的代码简单只有一行报错行,而复杂的代码会显示很多行,但是都是上一行的代码指向下一行,所以只有最后一行是真正的报错行。
蓝框报错行的代码,下面有波浪线的代码就是报错的具体代码。
绿框报错信息,表示最后一行报错行的具体错误原因。大部分报错都能通过报错信息找到原因,所以这很重要,看不懂就去翻译!!!翻译看不懂就百度!!!不会百度那用 ai 会吧!!! ai链接:文心一言
  1. 翻译报错信息。看不懂信息那就去 ai,把代码和报错给ai,ai会告诉你可能的原因。
    在这里插入图片描述

  2. 结合报错代码和报错信息。报错信息说 None对象没有text属性,报错代码是 res_tag.text。我们想要获得的是 res_tag 的text属性,因此可以说明 res_tag 是个 None对象。

    None对象就是 None(python中 None是个专门的类型,叫 None类型,就好像字符串类型、列表类型一样。不过 None只有一个值,就是它本身,代表空),这说明 res_tag 是个空的,没有值。

  3. 此时我们已经找到了产生报错的原因,那又是什么原因导致了 res_tag 是空值呢?因此我们 需要往上追根溯源, res_tag 来自上一行代码 res_tag = soup.find(“a”, href=“/book/xiyouji/1.tml”), 这说明这行代码并没有找到想要的标签。
    提示:find 方法在没有找到标签时就会返回空(None),这与报错信息刚好符合。 因此可能的原因就出现了:是查找的标签不存在。

  4. 因此就要检查自己写的标签是否正确,是不是标签的字母或者格式写错了?如果写得没有问题,但还是报错。就 继续往上追根溯源。

  5. 代码 res_tag = soup.find(“a”, href=“/book/xiyouji/1.tml”) 是在soup中通过 find方法查找标签,因此soup中有什么就决定了find能找到什么;
    而soup又是 response.text 通过html解析代码 soup = BeautifulSoup(response.text, ‘html.parser’) 得到的,因此response.text 是什么内容就决定了soup是什么内容;
    response.text 又是通过get请求 response = requests.get(url=url, headers=headers) 得到的,因此我们可以一层层打印上去,去看看获取到的网页源码数据是否与浏览器上一致。
    在这里插入图片描述
    在这里插入图片描述

  6. 通过上一步的打印soup 或 打印网页源码 (两者内容一致,打印哪个都可以),再通过与浏览器上的网页源码相比较,应该就能发现打印出来的源码和浏览器中并不一样,这就是找不到标签的 另一个原因:第一步爬取下来的html源码与实际的源码并不一致。 具体为什么想想上文问答中的最后两个问题。

如何解决:

  • 标签书写不正确就多查找资料多练习,没有取巧的办法。参考资料1参考资料2
  • 爬取的html源码与实际源码不一致可能是网站有反爬。完善请求头(添加User-Agent、Cookie、Referer 等参数)、增大爬取间隔时间、使用IP代理、使用selenium模拟浏览器 等办法能有效绕过反爬。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值