织梦网站模板如何安装,深圳网站建设zvge,网站建设简介联系方式,做网站系统开发的意义目录
web请求与requests库
1. web请求
1.1 客户端渲染与服务端渲染
1.2 抓包
1.3 HTTP状态代码
2. requests库
2.1 requests模块的下载
2.2 发送请求头与请求参数
2.3 GET请求与POST请求
GET请求的例子#xff1a;
POST请求的例子#xff1a; 3. 案例#xff1a;…目录
web请求与requests库
1. web请求
1.1 客户端渲染与服务端渲染
1.2 抓包
1.3 HTTP状态代码
2. requests库
2.1 requests模块的下载
2.2 发送请求头与请求参数
2.3 GET请求与POST请求
GET请求的例子
POST请求的例子 3. 案例爬取豆瓣电影榜
正则表达式与re库
1. 正则表达式
1.1 贪婪匹配
1.2 惰性匹配
2. re库
2.1 compile() - 创建正则对象
2.2 match()与search() - 单个匹配
2.3 findall()与finditer() - 所有匹配
2.4 sub() - 替换
2.5 split() - 分割
捕获组与非捕获组
3. 案例爬取豆瓣top250电影指定数据 web请求与requests库
1. web请求
web请求是指客户端向服务端发送的请求以此获得服务端提供的资源或者与服务端进行交互。其中客户端是发送请求的一方通常指浏览器、移动应用等服务端是响应的一方指运行在服务器上的web应用程序。
爬虫属于客户端通过向服务端发送web请求获取服务端的数据。
下面介绍常见的两种web请求类型这里暂不做详细介绍
http请求遵循http协议。httpshttp的加密版。
1.1 客户端渲染与服务端渲染
客户端渲染CSR指在客户端完成界面的渲染
服务端将基础的HTML骨架和源代码打包发给客户端客户端经加载源代码后再进行请求数据和界面渲染。因为服务端发送的并非成熟的HTML文件爬虫需要额外的开销来加载和执行源代码。
服务端渲染SSR指在服务端完成界面的渲染
服务端完成页面的渲染并将经渲染的HTML文件发送给客户端浏览器无需经过源文件的加载和执行便可直接展示界面。由于服务端提供了HTML文件爬虫可以直接获取完整的HTML文件而无需等待加载源文件因此服务端渲染对爬虫更为友好。
1.2 抓包
渲染方式不同获取URL的方式也略有不同。
基本步骤打开需要爬取的界面 - F12 - 刷新 - 网络 - 打开第一个数据包
服务端
第一个数据包黑色方框为数据因此该网页为服务端渲染。从该数据包预览页中可以看到页面的所有信息。 此数据包的标头存放着需爬取的URL。 客户端渲染
第一个数据包是HTML骨架没有完整的界面信息。 此时我们需要找到存放数据的包这个为爬虫需要爬的内容。 应使用该数据包的URL 1.3 HTTP状态代码 在抓包过程中我们注意到表头有一行状态代码显示“200 OK”表示请求成功、并返回了资源。在平时生活中也会遇到“404”、“304”等情况。“404”“304”与“200”一样都属于HTTP的状态代码用来表示HTTP请求的处理结果。这些状态代码被划分到了不同的类型具有独特的意义。我们需要熟记每一类状态码的意义。 1xx - 信息性状态码 100 Continue服务器已收到请求的第一部分正在等待其余部分。101 Switching Protocols服务器根据客户端的请求切换协议。 2xx - 成功状态码 200 OK请求成功服务器返回了请求的资源。201 Created请求成功服务器创建了新的资源。202 Accepted请求已接受但尚未处理完成。204 No Content请求成功但服务器没有返回内容。 3xx - 重定向状态码 301 Moved Permanently请求的资源已永久移动到新的URL。302 Found请求的资源临时移动到新的URL。304 Not Modified资源未修改客户端可以使用缓存的版本。 4xx - 客户端错误状态码 400 Bad Request请求格式错误。401 Unauthorized请求未授权需要身份验证。403 Forbidden服务器拒绝访问请求的资源。404 Not Found请求的资源未找到。405 Method Not Allowed请求的方法不被允许。 5xx - 服务器错误状态码 500 Internal Server Error服务器内部错误。501 Not Implemented服务器不支持请求的功能。502 Bad Gateway服务器作为网关时从上游服务器收到无效响应。503 Service Unavailable服务器暂时无法处理请求。504 Gateway Timeout服务器作为网关时上游服务器未在规定时间内响应。2. 2. requests库
requests是一个常用的python第三方库常用于发送HTTP请求。requests库封装了底层的HTTP协议的细节使得发送和响应HTTP请求变得十分轻松。
2.1 requests模块的下载
这里介绍采用命令行的方式下载winR - 打开cmd - 输入命令行
pip install requests
如果因为超时导致下载失败可以考虑延长pip等待时间通过--default timeout的方式设置超时时间。
pip install requests --default-timeout120 这样就下载成功了。
2.2 发送请求头与请求参数
请求头的获取
一些网址的爬取要求加上请求头这样可以让程序看起来更像真人。 请求参数 一些URL链接过长其原因是链接后面接了部分参数。可以通过发送请求参数减短URL链接。一般情况下“”后的数据为参数。
import requests# 设置请求头
headers {user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0}
#设置请求参数
params {q: 陈奕迅qs: nform: QBREsp: -1lq: 0pq: 陈奕迅sc: 13-3sk: cvid: D6F23A59983048E485AA76E7A663ED49ghsh: 0ghacc: 0ghpl: }#若不设置请求参数url为
#https://cn.bing.com/search?q%E9%99%88%E5%A5%95%E8%BF%85qsnformQBREsp-1lq0pq%E9%99%88%E5%A5%95%E8%BF%85sc13-3skcvidD6F23A59983048E485AA76E7A663ED49ghsh0ghacc0g
urlhttps://cn.bing.com/search
2.3 GET请求与POST请求
GET请求和POST请求是HTTP协议中最常用的两种请求方式。
GET请求通过URL发送请求访问页面资源参数在URL中传递是一种无副作用的请求方式。PORT请求参数包含在请求体中用于修改服务器上的数据是一种有副作用的请求方式。
GET请求的例子
import requests #导入requests模块url https://baike.baidu.com/item/陈奕迅/128029 #获取url链接
header{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0
}
resp requests.get(url,headersheader) #发送请求并用变量resp接收#添加user-agent表头使看起来更像真人访问
print(resp.text) 运行可以看到网页的编码出现在了运行结果处。这就是个简单的爬虫程序。 我们已经成功向服务端发送请求并获得了响应。接下来则需要将获取到的数据写入HTML文件中
try:resp requests.get(url,headersheader) #发送请求并用变量resp接收#请求成功将响应的内容存放至HTML文档中追加方式为w(写入),写入格式为utf-8。with open(eason.html,w,encodingutf-8) as file:file.write(resp.text)print(请求成功已将数据存放至HTML文件)
except Exception as e:print(请求失败)
运行将自送生成一个html文件。打开该文件即可浏览我们爬下来的页面。 POST请求的例子
以百度翻译为例子。当输入信息后会自动生成几个数据包。 筛选Fetch/XHR文档找到存放服务端返回内容的数据包即可得到对应的URL和数据表单。 import requests #导入requests模块url https://fanyi.baidu.com/sug #获取url链接headers{#模拟浏览器发送请求user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0
}
data{#模拟表单数据发送关键字applekw:apple
}
#发送post请求
resprequests.post(url,headersheaders,datadata)
#响应是json格式可以直接解析并打印。
print(resp.json())
运行即可获取返回的数据。 网页上显示的数据如下 3. 案例爬取豆瓣电影榜
找到存放豆瓣电影榜的数据包 URL中后的数据为参数可删去而用负载中的数据表示这些参数 import requests #导入requests模块urlhttps://movie.douban.com/j/chart/top_list
#请求头
headers{user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0}
#请求参数
params {type: 11,interval_id: 100:90,action:,start: 0,limit: 20
}
# 尝试发送 GET 请求
try:resp requests.get(url, headersheaders, paramsparams)print(resp.json()) # 尝试解析 JSON 数据
except Exception:print(请求失败!) 正则表达式与re库
1. 正则表达式
正则表达式是一种表示字符串的基本语法可以用来匹配字符串。
例如我们拿“\d”去匹配字符串“123ABC”可以得到3种匹配结果“\d”分别匹配1、2、3。 而正则对象“a*.”可以用来匹配“aaaaab”
“a*”中*可以匹配0次或多次前面元素a即“a*”可以匹配“aaaaa”而“.”可以匹配任意字符即“.”可以匹配“b”。因此正则对象“a*.”可以匹配字符串“aaaaab”。
下面是一些正则表达式的常见用法 \w 匹配单个字母/数字/下划线 \s 匹配单个空格 \d 匹配单个数字 \n 匹配单个换行符 \t 匹配单个制表符 ^ 匹配字符串的开始 匹配字符串的结尾 \W 匹配非数字、字母、下划线 \D 匹配非数字 \S 匹配非空白符 a|b 匹配a或b () 分组用于分组匹配或捕获子字符串 [] 字符集用于匹配括号内任意单个字符 . 匹配除换行符以外的任意单个字符 * 匹配前面元素0次或多次 匹配前面元素1次或多次 匹配前面元素0次或1次 {n} 匹配前面元素n次 {n,} 匹配前面元素n次或多次 {n,m} 匹配前面元素n次到m次
1.1 贪婪匹配
贪婪匹配是正则表达式中的一种匹配模式他的思想是尽可能匹配更长的字符串。如“\d”就是一种贪婪匹配模式能够尽可能多的匹配字符串中的数字。在字符串“abc~12345~de_67_”中对于正则对象“\d”可以找到两种匹配“12345”“67”这两种匹配已是最长。 再如“.*”也是一种贪婪匹配模式可以“a.*b”可以理解为忽略a与b间的内容找到最长的匹配。 1.2 惰性匹配
惰性匹配是正则表达式中的一种匹配模式与贪婪匹配相反他的思想是尽可能匹配更短的字符串。要想实现惰性匹配只需在量词后加上。如“\d”就是一种惰性匹配模式能够尽可能少的匹配字符串中的数字。在字符串“abc~12345~de_67_”中对于正则对象“\d”能找到的匹配是单个数字字符。因此“\d”就是一种惰性匹配。 再如“.*”也是一种惰性匹配模式可以“a.*b”可以理解为忽略a与b间的内容找到最短的匹配。 2. re库
re是python的标准库之一用于正则表达式的处理。
2.1 compile() - 创建正则对象
re.compile()用于创建新的正则对象。
import re#匹配1个或多个字符
pattern re.compile(r\d)# 匹配URL链接
url_pattern re.compile(r^(https?):// # 匹配 http、https 或 ftpr([a-zA-Z0-9.-]) # 域名r(:\d)? # 端口号r(/[^?\s]*)? # 路径r(\?[^#\s]*)? # 查询参数r(#\S*)?$ # 锚点
)
2.2 match()与search() - 单个匹配
match()与search()均用于查找字符串的第一个匹配区别在于match是从字符串最开始处匹配一旦这个字符串的最开始部分与正则表达式不匹配无论后面是否有子字符串与之匹配都将匹配失败而search()只需要找到与正则表达式匹配的子字符串无论这个子字符串是否在字符串开头。
re.match(pattern,text)判断字符首部是否与pattern匹配。
import repattern re.compile(r\d)
text[123abc456,abc456def]
match[re.match(pattern,text[0]),re.match(pattern,text[1])]for i in range(2):if match[i]:print(ftext[{i}]:匹配成功{match[i].group()})else:print(ftext[{i}]:匹配失败)#text[0]:匹配成功123#text[1]:匹配失败
pattern.search(text)用于判断字符串text中是否有与正则表达式匹配的子字符串若有则返回第一个匹配的字符串若没有返回None。
import repattern re.compile(r\d)
test abc123de456
matchpattern.search(test)if match:print(match.group()) #123
else:print(匹配失败)
2.3 findall()与finditer() - 所有匹配
findall()与finditer()都用于查找所有的匹配但他们的返回值有所不同findall()将返回与正则表达式匹配的子字符串列表而finditer()则返回一个迭代器每次迭代返回一个Match对象。关于Match对象的用法 match.group()返回匹配的字符串。 match.start()返回匹配的起始位置。 match.end()返回匹配的结束位置。 match.span()返回一个元组 (start, end)表示匹配的起始和结束位置。 pattern.findall(text)用于查找所有匹配并返回一个列表。
import repattern re.compile(r\d)
test abc123de456
matchpattern.findall(test)if match:print(match) #[123, 456]
else:print(匹配失败)
pattern.finditer(pattern,text)用于查找所有匹配并返回一个迭代器。
import retexthello,python!
pattern re.compile(r\w)
matchesre.finditer(pattern,text)# 使用迭代器逐个处理匹配结果
for match in matches:print(fMatch found: {match.group()} at position {match.start()}-{match.end()})
#Match found: hello at position 0-5
#Match found: python at position 6-12
2.4 sub() - 替换
re.sub(pattern,str,text)用str替换text中匹配正则对象pattern的内容。
import repattern re.compile(r\d)
test abc123de456resre.sub(pattern,x,test)print(res) #abcxdex
2.5 split() - 分割
re.split(pattern,text)依照正则对象pattern分割text与pattern匹配的字符串作为分割边界。
import repattern re.compile(r\d)
test abc123de456result re.split(pattern,test)
print(result) #[abc, de, ]捕获组与非捕获组
捕获组用(…)表示兼具分组和捕获的作用。经匹配过的字符串依照正则表达式进行分组通过.group(idx)的方式可以捕获不同分组。分组的下标从1开始。
如格式为YYYY-MM-DD的日期字符串我们希望对其进行分组从而能分别捕获年、月、日。那么对该字符串的分组为(YYYY)、(MM)、(DD)对应的正则表达式为(\d{4})-(\d{2})-(\d{2})
import repattern re.compile(r(\d{4})-(\d{2})-(\d{2})) #YYYY-MM-DD
text2025-01-01
matchre.match(pattern,text)
if match:#捕获不同分组yyyymatch.group(1)mmmatch.group(2)ddmatch.group(3)print(fYear:{yyyy},Month:{mm},Date:{dd}) #Year:2025,Month:01,Date:01
else:print(匹配失败)
在捕获组中可以添加“?name”来命名捕获组如(?namepattern)
非捕获组用(?:…)表示仅具有分组功能而无法对分组进行捕获。这里不再展示。
3. 案例爬取豆瓣top250电影指定数据
要求爬取数据电影名称、上映年份、国家、评分并把数据存入csv文件中。 如何用正则表达式表达爬取所需的格式
首先需要找到数据存放的位置。 选择图上这个图标点击“肖申克的救赎”可以快速定位数据所在位置。找到数据所在位置后我们找到它的最外层文件可以看到当光标停放在li这一行时《肖申克的救赎》这部电影的所有数据都囊括在阴影处。往下可以找到需要爬去的数据。因此我们的正则表达式可以从li开始接下来只需要表达式能特异性地识别到数据存放的位置。 依据上图最后的正则表达式为
(正则表达式不唯一)
objre.compile(rli.*?div classitem.*? #最外层及第二层文件rspan classtitle(?Pname.*?)/span.*? #电影名称rbr(?Pyear.*?)nbsp;/nbsp;(?Pcountry.*?)nbsp;/.*? #年份、国家rspan classrating_num propertyv:average(?Pscore.*?)/span, #评分re.S)
li.*?div classitem
“ .*? ”是一种惰性匹配*匹配任意字符.*? 意味着要尽量少的匹配字符直到出现下一次匹配。这里可以理解为忽略li与div classitem之间的内容。其他位置 “ .*? ”同理。
span classtitle
精确匹配HTML的标签这是电影名的开始处。其他处同理。
(?Pname.*?)
这是一个捕获组采用了 (?Pname…) 用于捕获电影名称并使其可以被name捕获。其他处同理。
/span
精确匹配HTML的标签这是电影名的结束位置。其他处同理。
nbsp;/nbsp;
HTML中相邻两项的分隔。
re.S
编译标志也被称为DOTALL模式使“ . ”可以匹配包括换行符在内的任意字符。
最后的程序
import requests
import re
import csvurl https://movie.douban.com/top250 #URL链接
headers { #请求头user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0
}try:#发送请求resprequests.get(url,headersheaders)#状态判断if resp.status_code!200:raise Exception(f状态码错误{resp.status_code})#创建正则表达式objre.compile(rli.*?div classitem.*?rspan classtitle(?Pname.*?)/span.*?rbr(?Pyear.*?)nbsp;/nbsp;(?Pcountry.*?)nbsp;/.*?rspan classrating_num propertyv:average(?Pscore.*?)/span,re.S)resultobj.finditer(resp.text)# 写入 CSV 文件with open(data.csv, modew, newline, encodingutf-8) as file:csvwriter csv.writer(file)csvwriter.writerow([Name, Year, Country, Score]) # 写入表头for match in result:dic match.groupdict()csvwriter.writerow([dic[name].strip(), dic[year].strip(), dic[country].strip(), dic[score].strip()])except Exception as e:print(f请求失败{e})
finally:print(程序结束)