Python3网络爬虫开发实战(2)爬虫基础库

文章目录

  • 一、urllib
    • 1. urlparse 实现 URL 的识别和分段
    • 2. urlunparse 用于构造 URL
    • 3. urljoin 用于两个链接的拼接
    • 4. urlencode 将 params 字典序列化为 params 字符串
    • 5. parse_qs 和 parse_qsl 用于将 params 字符串反序列化为 params 字典或列表
    • 6. quote 和 unquote 对 URL的中文字符进行编码和解码
  • 二、requests
    • 1. GET 请求
    • 2. POST 请求
    • 3. Session 维持
    • 4. 响应
    • 5. 身份认证
    • 6. 设置代理
    • 7. Prepared Request
  • 三、httpx
    • 1. Requests Compatibility
    • 2. 异步
  • 四、基础爬虫实战

一、urllib

urllib 类似于 python 底层构建请求,构建相对于其他的库来说较为复杂,不过 urllib 解析链接非常好用

1. urlparse 实现 URL 的识别和分段

如果需要合并 params 和 query 可以使用 urlsplit

from urllib.parse import urlparseurlparse('https://www.baidu.com/')# ParseResult(scheme='https', netloc='[www.baidu.com](https://www.baidu.com/)', path='/', params='', query='', fragment='')

2. urlunparse 用于构造 URL

urlunparse 这个方法接收的参数是一个可迭代对象,且其长度必须为 6;同样的,如果需要合并 params 和 query 可以使用 urlunsplit

from urllib.parse import urlunparsedata = ['https','www.baidu.com','index.html','user','a=6','comment']urlunparse(data)
# https://www.baidu.com/index.html;user?a=6#comment

3. urljoin 用于两个链接的拼接

urljoin 首先会解析 new_url,判断其 scheme,netloc,path 是否出现了缺失,如果确实使用 base_url 中的 scheme,netloc,path 对应缺失部分代替;

from urllib.parse import urljoinbase_url = 'https://www.baidu.com'
new_url = 'FAQ.html'urljoin(base_url, new_url)
# https://www.baidu.com/FAQ.html

4. urlencode 将 params 字典序列化为 params 字符串

from urllib.parse import urlencodeparams = {'name': 'germey','age': 2,
}base_url = 'https://www.baidu.com?'
base_url + urlencode(params)
# https://www.baidu.com?name=germey&age=2

5. parse_qs 和 parse_qsl 用于将 params 字符串反序列化为 params 字典或列表

from urllib.parse import parse_qs, parse_qslparams = 'name=germey&age=25'parse_qs(params, separator='&')
# {'name': ['germey'], 'age': ['25']}parse_qsl(params, separator='&')
[('name', 'germey'), ('age', '25')]

6. quote 和 unquote 对 URL的中文字符进行编码和解码

from urllib.parse import quote, unquoteurl = "https://www.baidu.com/s?wd=爬虫"# utf8编码,指定安全字符
quote(url, safe=";/?:@&=+$,", encoding="utf-8")
# https://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB# gbk编码,指定安全字符
quote(url, safe=";/?:@&=+$,", encoding="gbk")
# https://www.baidu.com/s?wd=%C5%C0%B3%E6# utf8解码
unquote('https://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB', encoding='utf-8')
# https://www.baidu.com/s?wd=爬虫# gbk解码
unquote('https://www.baidu.com/s?wd=%C5%C0%B3%E6', encoding='gbk')
# https://www.baidu.com/s?wd=爬虫

二、requests

1. GET 请求

测试 URL: www.httpbin.org/get

cookies 可以单独设置,也可以放在 headers 的 cookie 字段下传入请求之中,timeout 可以控制超时时间,headers 是请求头,params 是参数构建完整的 url;

import requestsparams = {}
headers = {}
cookies = {}# vertify 设置为 False 可以避免 ssl 认证
requests.get(url=url, params=params, headers=headers, cookies=cookies, vertify=False, timeout=None)

2. POST 请求

测试 URL: www.httpbin.org/post

POST 是上传东西的常用请求,POST 请求中除了 GET 请求中的那些参数,还有一些参数可以使用,如 data 和 file;其中 data 主要用来传表单,而 file 主要用来传文件;

import requestsparams = {}
headers = {}
cookies = {}data = {}
file = {}# vertify 设置为 False 可以避免 ssl 认证
requests.post(url=url, params=params, headers=headers, cookies=cookies, vertify=False, timeout=None, data=data, file=file)

3. Session 维持

多次直接利用 requests 库中的 get 或 post 方法模拟网络请求,相当于打开了多个不同的浏览器,而使用 Session 维持 搭配 get 和 post 方法去模拟网络请求,相当于打开了一个浏览器中的多个页面;

import requestss = requests.Session(headers=headers)
s.get(url_1)
s.get(url_2)# 这里在第一次 get 请求中获得到的 cookie 就会保持进而在第二次 get 请求中得到

4. 响应

import requestsresp = requests.get()# 状态码
resp.status_code# 响应头
resp.headers# cookies
resp.cookies# 最终 url 搭配重定向使用 requests.get(url, allow_redirects=False)
resp.url# 请求历史
resp.history# 在获取 resp.text 先配置 encoding
resp.encoding# 响应结果字符串形式,需要搭配 resp.encoding = 'utf-8' or 'gbk' 使用
resp.text# 二进制相应结果,通常对应于文件
resp.content# resp.text 转化为 json 数据,如果不是json 数据格式,则会出现解析错误,抛出 json.decoder.JSONDecodeError 异常
resp.json

5. 身份认证

在访问启用了基本身份认证的网站时,首先会弹出一个认证窗口,认证正确会弹出 200状态码,如果认证错误或者不进行认证会弹出 401 错误;

import requests
from requests.auth import HTTPBasicAuth# 第一行是第二行的简写
r = requests.get('https://ssr3.scrape.center/',auth=('admin','admin'))
r = requests.get('https://ssr3.scrape.center/',auth=HTTPBasicAuth('admin','admin'))r.status_code
# 200

requests 库还提供了其他的认证方式,如 OAuth 认证,需要安装 oauth 包;

6. 设置代理

首先是基本的 HTTP 代理

import requestsproxies = {'http':'http://10.10.10,10:1080','https':'https://10.10.10.10:1080',
}requests.get('https://www.httpbin.org/get', proxies=proxies)

除了基本的 HTTP 代理外,还支持 SOCKS 协议的代理,首先需要安装 socks 库 pip install requests[socks]

import requestsproxies = {'http':'socks5://10.10.10,10:1080','https':'socks5://10.10.10.10:1080',
}requests.get('https://www.httpbin.org/get', proxies=proxies)

7. Prepared Request

因此多个 get 或者 post 请求相当于多个 Session,尽量避免对同一网页使用多个 get 或者 post 请求

from requests import Request,Sessionurl = 'https://www.httpbin.org/post'
data = {'name':'germey'}
headers = {}# 请求的底层
s = Session()
req = Request('POST', url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)# 等价
r = requests.post(url, data=data, headers=headers)

三、httpx

HTTPX 建立在 requests 完善的可用性之上,支持 HTTP/2 并支持异步;HTTPX (python-httpx.org)

可选安装如下:

  • h2 - HTTP/2 支持。 (可选,带有 httpx[http2]
  • socksio - SOCKS 代理支持。 (可选,带有 httpx[socks]
  • brotlibrotlicffi - 解码“brotli”压缩响应。 (可选,带有 httpx[brotli]

HTTPX 与 requests 的 API 广泛兼容,在少部分地方存在一些设计差异:Requests Compatibility - HTTPX (python-httpx.org)

1. Requests Compatibility

重定向:与 requests 不同,HTTPX 默认情况下是不遵循 重定向 (redirects) 的,开启重定向如下所示

client = httpx.Client(follow_redirects=True)
response = client.get(url, follow_redirects=True)

Client:等价于 requests.Session 维持,即等价

session = requests.Session(**kwargs)
client = httpx.Client(**kwargs)

URL:访问 response.url 将返回 url 实例,requests 返回的是字符串

重定向请求requests 库公开了一个属性 response.next ,该属性可用于获取下一个重定向请求。在 HTTPX 中,此属性被命名为 response.next_request

# requests
session = requests.Session()
request = requests.Request("GET", ...).prepare()
while request is not None:response = session.send(request, allow_redirects=False)request = response.next# httpx
client = httpx.Client()
request = client.build_request("GET", ...)
while request is not None:response = client.send(request)request = response.next_request

请求内容:对于上传原始文本或二进制内容,httpx 使用 content 参数,以便更好地将这种用法与上传表单数据的情况分开。使用 content=... 上传原始内容,并使用 data=... 发送表单数据;

httpx.post(..., content=b"Hello, world")
httpx.post(..., data={"message": "Hello, world"})

上传文件:HTTPX 严格强制上传文件必须以二进制模式打开,以避免尝试上传以文本模式打开的文件可能导致的字符编码问题。

内容编码:HTTPX 使用 utf-8 来编码 str 请求正文。例如,当使用 content=<str> 时,请求正文将在通过线路发送之前编码为 utf-8

Cookietrust_envverifycert 参数:如果使用客户端实例,应始终在客户端实例化时传递,而不是传递给请求方法。

2. 异步

requests 是不支持异步的,通常我们会使用 aiohttp 来进行异步操作,而 httpx 不仅支持同步还支持异步

import asyncio
import httpxasync def main():async with httpx.AsyncClient() as client:response = await client.get('https://www.example.com/')print(response)asyncio.run(main())

四、基础爬虫实战

任务:

  1. 使用爬虫基本库爬取 https://ssr1.scrape.center/ 每一页的电影列表,顺着列表再爬取每个电影的详细页
  2. 使用正则表达式提取每部电影的名称,封面,类别,上映时间,剧情简介等内容;
  3. 使用多进程实现爬取的加速;

流程:

代码:

import os
import re
import httpx
import json
from multiprocessing import Pool
from urllib.parse import urljoinbase_url = "https://ssr1.scrape.center"def scrape_index(page):"""获得page的url"""page_url = f"{base_url}/page/{page}"return page_urldef scrape_list(html):"""获得列表的url"""url_list = re.findall(r'<a data.* href="(.*)" class="name">', html)url_list = [urljoin(base_url, item) for item in url_list]return url_listdef scrape_detail(html):"""获得详细页信息"""detail_dic = {}detail_dic["名称"] = (re.search(r'<h2 data.*? class="m-b-sm">(.*?)</h2>', html, re.S).group(1)if re.search(r'<h2 data.*? class="m-b-sm">(.*?)</h2>', html, re.S)else None)detail_dic["封面"] = (re.search(r'class="item.*?<img.*?src="(.*?)".*?class="cover">', html, re.S).group(1)if re.search(r'class="item.*?<img.*?src="(.*?)".*?class="cover">', html, re.S)else None)detail_dic["类别"] = re.findall(r"<button.*?category.*?<span>(.*?)</span>.*?</button>", html, re.S)detail_dic["上映时间"] = (re.search(r"<span>.*?(\d{4}-\d{2}-\d{2}) 上映", html, re.S).group(1)if re.search(r"<span>.*?(\d{4}-\d{2}-\d{2}) 上映", html, re.S)else None)detail_dic["剧情简介"] = (re.search(r"剧情简介</h3>.*?<p.*?>(.*?)</p>", html, re.S).group(1).strip()if re.search(r"剧情简介</h3>.*?<p.*?>(.*?)</p>", html, re.S)else None)return detail_dicdef validateTitle(title):"""命名规范性"""rstr = r"[\/\\\:\*\?\"\<\>\|]"  # '/ \ : * ? " < > |'new_title = re.sub(rstr, "_", title)  # 替换为下划线return new_titledef save_json(detail_dic):"""保存数据到json文件夹下"""os.makedirs("./json", exist_ok=True)name = detail_dic["名称"]data_path = f"./json/{validateTitle(name)}.json"json.dump(detail_dic, open(data_path, "w", encoding="utf-8"), ensure_ascii=False, indent=2)def main(page):client = httpx.Client()page_url = scrape_index(page)resp_page = client.get(page_url).texturl_list = scrape_list(resp_page)for detail_url in url_list:resp_detail = client.get(detail_url).textdetail_dic = scrape_detail(resp_detail)save_json(detail_dic)if __name__ == "__main__":pool = Pool(10)pages = range(1, 10 + 1)pool.map(main, pages)pool.close()pool.join()

得到结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/50092.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GIS前沿技术

无论是初步接触到GIS的学生&#xff0c;还是对GIS已经有一定的了解的从业者&#xff0c;肯定都非常关心两个问题&#xff1a;GIS有没有发展前景&#xff0c;GIS有哪些应用价值&#xff1f; 关于这两个问题&#xff0c;笔者的答案是GIS作为一门融合了空间数据采集、存储、处理、…

【数据结构】堆,优先级队列

目录 堆堆的性质大根堆的模拟实现接口实现构造方法建堆入堆判满删除判空获取堆顶元素 Java中的PriorityQueue实现的接口构造方法常用方法PriorityQueue注意事项 练习 堆 如果有一个集合K {k0&#xff0c;k1&#xff0c; k2&#xff0c;…&#xff0c;kn-1}&#xff0c;把它的…

Listen(sockfd,backlog)监听函数的第二个参数到底是什么?深度解释

listen队列剖析 int listen(int sockfd,int backlog) backlog : 监听套接字队列 对于一个调用监听的套接字&#xff0c;系统会维护给这个套接字两个队列 1. 未完成连接队列 //当客户端发生三次握手的第一次syn包给服务器的时候&#xff0c;服务器就会再未完成队列中创建…

2024第29届郑州全国商品交易会

第29届郑州全国商品交易会 2024第四届餐饮与供应链专题展 邀 请 函郑州全国商品交易会&#xff08;简称郑交会&#xff09;是全国大型性经贸活动&#xff0c;一直秉承“政府指导&#xff0c;市场化运作”的模式&#xff0c;自1995年以来已成功举办了二十八届&#xff0c;是国内…

安装caffe-CPU版本并进行训练

目录 前言 0、安装Ubuntu 18.04 版本 输入ls没有反应 ubuntu换源 换源出现的问题 1、安装caffe出现E:Unable to locate package caffe-cpu问题 2、把 code 文件夹下载到 ubuntu 3、在本地使用caffe-CPU&#xff0c;并部署数据标注工具 ATool 问题1 问题2 问题3 命令行…

leedcode-数组-15 最接近的三数之和

原理 1、对数组进行升序排列&#xff1b; 2、定义变量_min&#xff0c;初始值是升序后数组的前3个元素之和&#xff0c;默认当前3个数之和离目标值最近&#xff1b; 3、遍历数组&#xff1b; 4、定义首指针为start&#xff0c;表示当前遍历元素的下一个元素&#xff0c;即i…

URL过滤、DNS过滤和内容过滤的总结

目录 URL过滤 URL和URI URL -- 统一资源定位符 URI --- 统一资源的标识符 URL和URI之间的区别 URL过滤的方式 HTTP协议获取URL的方式 HTTP协议做控制管理的流程 HTTPS协议做控制管理的流程 1&#xff0c;配置SSL的解密功能 2&#xff0c;直接针对加密流量进行过滤 例…

解决 Shiro 重复调用 doGetAuthenticationInfo 导致异常处理错误的问题

遇到一个 Shiro 中反复调用 doGetAuthenticationInfo 导致异常没有被成功处理的问题&#xff0c;经过一些源码调试&#xff0c;发现了问题的所在&#xff0c;只需在继承 BasicHttpAuthenticationFilter 的类中重写 onAccessDenied 方法即可。 文章目录 1.问题环境2.问题描述3.问…

2024-07-23 Unity AI行为树2 —— 项目介绍

文章目录 1 项目介绍2 AI 代码介绍2.1 BTBaseNode / BTControlNode2.2 动作/条件节点2.3 选择 / 顺序节点 3 怪物实现4 其他功能5 UML 类图 项目借鉴 B 站唐老狮 2023年直播内容。 点击前往唐老狮 B 站主页。 1 项目介绍 ​ 本项目使用 Unity 2022.3.32f1c1&#xff0c;实现基…

25.x86游戏实战-理解发包流程

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

【iOS】——Block循环引用

循环引用原因 如果在Block中使用附有_ _strong修饰符的对象类型自动变量&#xff0c;那么当Block从栈复制到堆时&#xff0c;该对象为Block所持有&#xff0c;这样容易引起循环引用。 HPPerson *person [[HPPerson alloc] init];person.block ^{NSLog("person.age--- …

服务韧性工程(SRE)论坛演讲实录 | 雅菲奥朗: 人工智能的未来之路引领智能运维新纪元

2024年5月24日&#xff0c;第二届服务韧性工程&#xff08;SRE&#xff09;论坛在杭州成功举办。本次会议由中关村人才协会作为指导单位&#xff0c;中国移动通信集团浙江有限公司和SRE创新联合体&#xff08;中关村人才协会SRE专委会&#xff09;联合主办,中移动信息技术有限公…

Linux 某进程 CPU 高问题,用 Shell 脚本发现处理

发现高CPU使用率进程 首先&#xff0c;我们需要编写一个Shell脚本来发现系统中CPU使用率最高的进程。以下是一个简单的脚本示例&#xff1a; #!/bin/bash# 设置 CPU 使用率的阈值,一般设置90&#xff1b;这里是demo&#xff0c;所以用30 CPU_THRESHOLD30# 获取占用 CPU 最高的…

pikauchu之Unsafe Fileupload(不安全的文件上传)

Client check&#xff08;客户检查&#xff09; 第一步先新建一个一句话木马 <?php eval($_POST[1]);?> 然后上传文件 有限制&#xff0c;只能上传那几种类型 现在看看源代码 我们将一句话木马文件的后缀改为png 然后用burp抓包&#xff0c;将png改成php 就能上传成功 …

运维上云/直播上云EasyNVS视频上云管理平台配置域名时的注意事项

EasyNVS视频上云管理平台拥有完整的视频流媒体服务能力和运维管理服务能力&#xff0c;不仅可以通过平台对EasyNVR、EasyGBS进行统一管理&#xff0c;还能解决设备现场没有固定公网IP却需要在公网直播的需求。 有用户反馈&#xff0c;在项目现场配置了EasyNVS的HTTPS证书&#…

Studying-代码随想录训练营day44| 1143.最长公共子序列、1035.不相交的线、53.最大子序和、392.判断子序列

第44天&#xff0c;动态规划part11&#xff0c;子序列题型part02(ง •_•)ง&#x1f4aa;&#xff0c;编程语言&#xff1a;C 目录 1143.最长公共子序列 1035.不相交的线 53.最大子序和 392.判断子序列 总结 1143.最长公共子序列 文档讲解&#xff1a;代码随想录最长公…

【微信小程序实战教程】之微信小程序原生开发详解

微信小程序原生开发详解 微信小程序的更新迭代非常频繁&#xff0c;几乎每个月都会有新版本发布&#xff0c;这就会让初学者感觉到学习的压力和难度。其实&#xff0c;我们小程序的每次版本迭代都是在现有小程序架构基础之上进行更新的&#xff0c;如果想要学好小程序开发技术&…

面试经典 114. 二叉树展开为链表

最近工作越来越难找&#xff0c;裁员越来越懂了&#xff0c;焦虑的睡不着&#xff0c;怎么办呢&#xff0c;只能刷面试题&#xff0c;卷死你们 今天这个题目没刷过&#xff0c;我思考了半天才只能用暴力&#xff0c;后来苦思冥想才想出来简单的方法&#xff0c;废话不多说&…

【机器学习】激活函数:神经网络的灵魂

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 激活函数&#xff1a;神经网络的灵魂什么是激活函数?常见激活函数类型1. Sigmo…

深入了解 JMeter 中的响应断言

JMeter 是一个强大的性能测试工具&#xff0c;能够模拟大量用户并发访问网站或应用程序&#xff0c;以便测试其性能和稳定性。在进行性能测试时&#xff0c;我们需要对响应结果进行断言&#xff0c;以确保应用程序或网站的功能和性能符合预期。 JMeter 提供了一套丰富的响应断…