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

news2024/9/23 11:17:02

文章目录

  • 一、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 urlparse

urlparse('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 urlunparse

data = ['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 urljoin

base_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 urlencode

params = {
    '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_qsl

params = '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, unquote

url = "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 requests

params = {}
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 requests

params = {}
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 requests

s = requests.Session(headers=headers)
s.get(url_1)
s.get(url_2)

# 这里在第一次 get 请求中获得到的 cookie 就会保持进而在第二次 get 请求中得到

4. 响应

import requests

resp = 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 requests

proxies = {
    '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 requests

proxies = {
    '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,Session

url = '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 httpx

async 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 urljoin

base_url = "https://ssr1.scrape.center"


def scrape_index(page):
    """获得page的url"""
    page_url = f"{base_url}/page/{page}"
    return page_url


def 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_list


def 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_dic


def validateTitle(title):
	"""命名规范性"""
    rstr = r"[\/\\\:\*\?\"\<\>\|]"  # '/ \ : * ? " < > |'
    new_title = re.sub(rstr, "_", title)  # 替换为下划线
    return new_title


def 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).text
    url_list = scrape_list(resp_page)
    for detail_url in url_list:
        resp_detail = client.get(detail_url).text
        detail_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.coloradmin.cn/o/1946574.html

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

相关文章

通信原理思科实验五:家庭终端以太网接入Internet实验

实验五 家庭终端以太网接入Internet实验 一实验内容 二实验目的 三实验原理 四实验步骤 1.按照上图选择对应的设备&#xff0c;并连接起来 为路由器R0两个端口配置IP 为路由器R1端口配置IP 为路由器设备增加RIP&#xff0c;配置接入互联网的IP的动态路由项 5.为路由器R1配置静…

Mysql-索引视图

目录 1.视图 1.1什么是视图 1.2为什么需要视图 1.3视图的作用和优点 1.4创建视图 1.5更新视图 1.6视图使用规则 1.7修改视图 1.8删除视图 2.索引 2.1什么是索引 2.2索引特点 2.3索引分类 2.4索引优缺点 2.5创建索引 2.6查看索引 2.7删除索引 1.视图 1.1什么是…

[Javascript】前端面试基础3【每日学习并更新10】

Web开发中会话跟踪的方法有那些 cookiesessionurl重写隐藏inputip地址 JS基本数据类型 String&#xff1a;用于表示文本数据。Number&#xff1a;用于表示数值&#xff0c;包括整数和浮点数。BigInt&#xff1a;用于表示任意精度的整数。Boolean&#xff1a;用于表示逻辑值…

流量录制与回放:jvm-sandbox-repeater工具详解

在软件开发和测试过程中&#xff0c;流量录制与回放是一个非常重要的环节&#xff0c;它可以帮助开发者验证系统在特定条件下的行为是否符合预期。本文将详细介绍一款强大的流量录制回放工具——jvm-sandbox-repeater&#xff0c;以及如何利用它来提高软件测试的效率和质量。 …

linux进程——解析命令行参数——环境变量详解

前言&#xff1a;本节内容还是linux进程&#xff0c; 主要讲解里面的环境变量——我们首先要知道的就是环境变量其实就是操作系统维护的一组kv值&#xff0c; 环境变量是系统提供的一组 变量名变量值 形式的变量。不同的环境变量之间具有不同的用途&#xff0c; 并且具有全局属…

刷机维修进阶教程-----何谓“tee损坏” 指纹丢失 掉帧 传感器失效?详细修复步骤教程

TEE损坏指的是安卓机型中Key Attestation密钥认证所依赖的可信应用中的证书库被破坏了。然后拒绝为指纹密匙认证提供服务。加密的密匙由TEE负责管理。tee损坏只影响当前机型的密匙认证。不影响加密。通俗的理解。如果你机型维修或者刷机或者解锁或者格机 全檫除分区等等后有异常…

Python自然语言处理库之NLTK与spaCy使用详解

概要 自然语言处理(NLP)是人工智能和数据科学领域的重要分支,致力于让计算机理解、解释和生成人类语言。在Python中,NLTK(Natural Language Toolkit)和spaCy是两个广泛使用的NLP库。本文将详细介绍NLTK和spaCy的特点、功能及其使用方法,并通过具体示例展示如何使用这两…

押金原路退回,手机版一键操作秒到账,无需设备收银设备

传统收银 1.操作不熟练&#xff1a;对收银系统的功能和操作不熟悉&#xff0c;可能导致收银过程较长&#xff0c;顾客等待时间增加。 2无法适应新技术&#xff1a;对于一些新的支付方式或技术&#xff0c;不能自主学 3操作不熟练&#xff1a;鼠标使用不熟练&#xff0c;对收…

element DatePicker 日期选择器,只选择月,月份数据从0开始(0月31日),而不是从1开始,JavaScript的原因,如下为解决办法

<el-date-pickerv-model"queryParam.yuedTime"type"month"placeholder"选择月"change"handleMonthChange"></el-date-picker> 方式一&#xff1a;在前端处理 change"handleMonthChange" &#xff0c;增加此方…

PostgreSQL的学习心得和知识总结(一百四十九)|psql 的使用技巧:设置、预设、回显和已保存的查询

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

nms概念

nms基本概念&#xff1a;非极大值抑制 用途&#xff1a;在做目标检测的时候&#xff0c;往往会生成很多很多候选框&#xff0c;在做目标检测的时候&#xff0c;往往会生成很多很多候选框。 处理流程&#xff1a; 1.对某一类按score对候选框进行排序&#xff0c;并选出score最…

ffmpeg把pcm封装为wav

note 1.wav格式中&#xff0c;音频数据未经过压缩&#xff0c;直接封装即可 2.对于编码器的选择&#xff0c;应选择和pcm裸数据一致的编码器(本次实际不须编码) version #define LIBSWRESAMPLE_VERSION_MAJOR 2 #define LIBSWRESAMPLE_VERSION_MINOR 9 #define LIBSWRESAM…

Python网络爬虫详解:实战豆瓣电影信息采集

文章目录 前言一、爬虫是什么&#xff1f;二、常用库及其作用1.Requests2.BeautifulSoup3. lxml4. Scrapy5. Selenium6. PyQuery7. Pandas8. JSON9. Time 三、实现步骤步骤一&#xff1a;环境准备步骤二&#xff1a;数据采集步骤三&#xff1a;数据处理步骤四&#xff1a;数据存…

【数据分享】2008-2022年我国省市县三级的逐日NO2数据(excel\shp格式)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000-2022年的省市县三级的逐日PM2.5数据、2013-2022年的省市县三级的逐日CO数据和2013-2022年的省市县三级的逐日SO2数据&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff01; 本次…

前端 SSE 长连接

使用 const options {withCredentials: true, // 默认 false}const eventSource new EventSource(/api, options);eventSource.addEventListener(open, () > {});eventSource.onmessage (event) > {}; // 或addEventListener(message,callback)eventSource.addEvent…

BGP选路之AS-PATH

原理概述 当一台BGP路由器中存在多条去往同一目标网络的BGP路由时&#xff0c;BGP协议会对这些BGP路由的属性进行比较&#xff0c;以确定去往该目标网络的最优BGP路由。首先要比较的属性是 Preferred Value&#xff0c;然后是Local Preference&#xff0c;再次是路由生成方式&a…

Ansible的脚本-----playbook剧本【上】

目录 1.playbook剧本组成 2.playbook剧本实战演练 2.1 实战演练一&#xff1a;给被管理主机安装httpd服务 2.2 实战演练二&#xff1a;定义、引用变量 2.3 实战演练三&#xff1a;指定远程主机sudo切换用户 2.4 实战演练四&#xff1a;when条件判断 2.5 实战演练五&…

Docker Compose V2 安装 ClickHouse v20.6.8.5 经验分享

前言 ClickHouse 是一款开源的分布式列式数据库管理系统,专门设计用于高性能的大数据分析和查询。 目前项目中用到的一个场景是将mongo的数据同步到clickhouse,使用clickhouse做报表,后续也将分享同步和使用方案 使用 Docker Compose 部署单机版,小项目和自己测试够用了,生…

【C#】visual studio打包winForm(依赖DLL)为安装程序exe

0.简介 IDE&#xff1a;VS2022 平台&#xff1a;C# .NetFramework4.7 WinForm界面 有GDAL、EEplus库的依赖&#xff0c;所以在其他未安装环境的电脑中功能无法使用。 1. 安装 1.1 运行文件 在VS扩展中选择管理扩展&#xff0c;Microsoft Visual Studio Installer Projects …

C#测试控制台程序调用Quartz.NET的基本用法

Quartz.Net是常用的任务调用框架之一&#xff0c;既能在客户端程序中使用&#xff0c;也支持在网页程序后台调用。本文结合参考文献4中的示例代码学习其在控制台程序中的基本用法。   VS2022新建控制台项目&#xff0c;在Nuget包管理器中搜索并安装Quartz包&#xff0c;如下所…