声明
1 本文内容来自自我学习总结,网络搜索整合。博客仅做学习用途。
2 本文部分内容可能存在错误,欢迎各位评论探讨以共同进步。
第一部分:相关概念
1.1 聚焦爬虫
所谓聚焦就是把焦点聚集在感兴趣的地方进行爬取数据,针对页面数据的某一部分进行爬取
1.2 页面请求与响应
通过观察页面上开发者工具_检查(f12)可以看出页面上有很多的数据包,数据包中包含着目标页面的请求地址,服务器收到请求后会响应返回响应数据。请求分为POST、GET请求。响应数据有页面字符串数据,JSON数据,二进制数据等。
1.3 AJAX请求
阿贾克斯请求是页面的某一部分收到请求而动态显示的请求。比如有些网址中的右侧下拉框在下拉时页面下方刷新出新的页面数据,同时页面右侧下拉框又回到了页面右侧中央位置。再比如一些页面的搜索请求,奖结果显示在页面某个位置,将搜索内容删除后页面结果也随之消失。
1.4 代理
一些机器的IP地址被服务器停止服务或者封禁之后可以在一些平台购买代理服务,原理就是将本机的数据包发送给代理商,代理商再将数据包发送给服务器。
1.5 进程、线程、协程
进程和线程大家都比较了解了,这三种任务执行单位都在python语言中有各自的模块。这里主要讲一下协程。协程是一般是线程中的任务执行单位,是用户级别的协作式任务调度机制,相比较线程来说,协程对于CPU的资源的占用少,因为线程调度是在系统内核进行,而协程是在用户空间进行的,这就说明线程在上下文切换的时候比协程上下文切换花销大。在一些高并发的网络服务时用的协程应用广泛。此外,线程中可以有堵塞操作,此时堵塞操作可以不消耗cpu资源,待可以执行时使用cpu资源,而协程中不可以使用堵塞操作,每个任务都是非堵塞或者快速交替进行的,这就使得在协程中加入类似堵塞的操作时需要挂起(await)。最后,协程由用户(程序员)编写,可以使用task、future等机制获取协程执行状态以及回调函数。
第二部分 实战
2.1 ajax请求爬取百度翻译数据
实战分析:
1 百度翻译页面有老版和新版之分,此实战基于老版
2 UA伪装是将程序模成一个浏览器向服务器发送请求。
3 如何确定请求百度翻译的数据是一个ajax请求呢? 在输入搜索内容时候页面网址没有发生变化,同时会动态的加载翻译结果。初步分析为一个阿贾克斯请求,之后F12查看网络数据包中的XHR数据包确认。
4 如何将请求参数发送给服务器的?参数格式是什么,这个要观察上述数据包携带的参数
import requests
import json
if __name__ == '__main__':
url="https://fanyi.baidu.com/sug"
headers={
'user-agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0"
}
kw=input('请输入要查询的关键字(英文):')
#kw关键字在edge浏览器中检查中的负载里 作为post请求的参数
data={
'kw':kw
}
response=requests.post(url=url,headers=headers,data=data)
if response.ok:
response_text=response.text
print(response_text) #因为响应结果类型是application/json 如果直接打印 打印出来的是一个字符串类型的数据
#将json字符串转化为json格式对象
dic_obj=response.json()
#打印对象
print(dic_obj)
#数据保存
filename="../../练习结果存储/"+kw+".json"
with open(filename,'w',encoding='utf-8') as file:
#file.write(dic_obj)#直接将字典对象写入文件会报错TypeError: write() argument must be str, not dict 需要用json对象写入方式
json.dump(dic_obj,fp=file,ensure_ascii=False)
一 乱码 (两种方法同时只能用一种)
1 将获取网页源码整体编码格式进行修改
response.encoding='utf-8' 或者 response.encoding='gbk'
2 针对局部乱码的位置进行通用编码格式修改
str=str.encode('iso-8859-1').decode('gbk')
二 列表写入文件
列表数据类型不能直接写入到文件中
1 可以将列表转化为字符串后写入文件 str='\n'.join(list) 列表元素以'\n'分隔转化为字符串str
2 遍历写入
三 字典写入文件
将字典转换为json字符串 然后打开文件操作后json.dump()
四 xpath注意
1 响应文本不是页面元素文本,二者有区别
2 xpath定位不到
<a class="bili-video-card__image--link" href="//www.bilibili.com/video/BV1ep421X7LP/" target="_blank">
<div class="bili-video-card__image __scale-player-wrap bili-video-card__image--hover">
<div class="bili-video-card__image--wrap">
<!---->
<picture class="v-img bili-video-card__cover">
<!--[-->
<source srcset="//i2.hdslb.com/bfs/archive/79d5f234b2359d449e4083afb4f7ce19588ccab7.jpg@672w_378h_1c.avif" type="image/avif">
<source srcset="//i2.hdslb.com/bfs/archive/79d5f234b2359d449e4083afb4f7ce19588ccab7.jpg@672w_378h_1c.webp" type="image/webp">
<img src="//i2.hdslb.com/bfs/archive/79d5f234b2359d449e4083afb4f7ce19588ccab7.jpg@672w_378h_1c" alt="【浅谈】记忆的奔流 《你想活出怎样的人生》观后笔记" loading="lazy" onload onerror="typeof window.imgOnError === 'function' && window.imgOnError(this)">
<!--]-->
</picture>
</div>
<div class="bili-video-card__mask">
<div class="bili-video-card__stats">
<div class="bili-video-card__stats--left">
<!--[-->
<span class="bili-video-card__stats--item">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" width="24" height="24" fill="#ffffff" class="bili-video-card__stats--icon">
<!--[-->
<!--]-->
</svg>
<span class="bili-video-card__stats--text">1.4万</span>
</span>
<!--]-->
<span class="bili-video-card__stats--item">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" width="24" height="24" fill="#ffffff" class="bili-video-card__stats--icon">
<!--[-->
<!--]-->
</svg>
<span class="bili-video-card__stats--text">0</span>
</span>
</div>
<span class="bili-video-card__stats__duration">59:25</span>
</div>
</div>
</div>
</a>
案例:获取上述代码中为了获取img标签中的alt属性
错误定位方法: '//a/div/div[1]/picture/img/@alt'
正确定位方法: '//a/div/div[1/picture/source/source/img/@alt' 或者//a/div/div[1/picture//img/@alt'