HTTP请求可以使用多种请求方法,但是爬虫最主要就两种方法:GET和POST方法。
get 请求:
一般情况下,只从服务器获取数据下来,并不会对服务器资源产生任何影响的时候会使用 get 请求。post 请求:
向服务器发送数据(登录)、上传文件等,会对服务器资源产生影响的时候会使用 post 请求。? 以上是在网站开发中常用的两种方法。并且一般情况下都会遵循使用的原则。但是有的网站和服务器为了做反爬虫机制,也经常会不按常理出牌,有可能一个应该使用get 方法的请求就一定要改 成post 请求,这个要视情况而定。
注意:
首先爬虫要引用 requests 内置库
import requests # 数据请求模块 pip install requests
# requests.get 发送一个 https://www.baidu.com/ 的请求
# 服务器接受到请求后会响应数据内容
response = requests.get('https://www.baidu.com/')
# 对象有对象的方法和属性
# .text 获取 Response 对象的文本内容
response.encoding = response.apparent_encoding
print(response.text)
"""
爬虫项目实现步骤:
1. 找数据对应的请求地址
静态网页: 在网页源代码能够找到的数据, 属于静态数据, 对应的地址是当前页面地址导航栏的地址
动态网页
2. 通过代码发送地址请求
3. 提取需要的数据内容, 剔除不需要的
4. 保存数据
"""
''' 示例 - 51游戏首页爬取 '''
# https://code.51.com/jh/tg1/i11/ld2j29ic.html
import requests
# 1.指定url
url = 'https://code.51.com/jh/tg1/i11/ld2j29ic.html'
# 2.发起请求
# get会返回一个响应对象。
response = requests.get(url=url)
# 3.获取响应数据
page_text = response.text # text表示获取字符串形式的响应数据
# print(page_text)
# 4.持久化存储
with open('51game.html', 'w', encoding='utf-8') as fp:
fp.write(page_text)
URL(外文名:Uniform Resource Locator,中文名:统一资源定位符),统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息是指出文件的位置以及浏览器应该怎么处理它。它最初是由蒂姆·伯纳斯·李发明用来作为万维网的地址,现在它已经被万维网联盟编制为互联网标准了。
注意:
在Internet上所有资源都有一个独一无二的URL地址,我们可以通过在地址栏中输入URL实现对资源的访问。
URL格式:
协议类型://服务器地址或IP地址[:端口号]/路径/文件名[参数=值]。
import requests
response = requests.get('https://www.ku6.com/video/feed?pageNo=0&pageSize=40&subjectId=72')
"""
https://www.ku6.com/video/feed?pageNo=0&pageSize=40&subjectId=72
https:// 请求协议类型
www 服务器名字 www(world wide web) 万维网; mail(邮箱服务器名字)
ku6.com 服务器域名
/ 服务器根目录
video/feed?pageNo=0&pageSize=40&subjectId=72 资源路径
url地址/连接地址/api地址/api接口
"""
import requests
"""
当我们请求不到数据的时候需要考虑, 是不是被反扒了, 是不是被检测到了
"""
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Cookie': 'll="118267"; bid=VrC8tT1GWz8; __gads=ID=744f53c3cb2ebb52-22841ef3a4e00021:T=1683638065:RT=1683638065:S=ALNI_MZhRKuML1OBDnNRafe3qd6-ndhaiQ; __gpi=UID=00000c03bafcda5c:T=1683638065:RT=1683638065:S=ALNI_MbkLLsUm467wiS6ZZ6Mn2ohKIWBZw; __yadk_uid=iHqVKZD4ZHIVREbOrlu9k4uWFSsAdZtO; _pk_id.100001.4cf6=b39d476add4f5658.1683638062.; ap_v=0,6.0; __utmc=30149280; __utmc=223695111; __utma=30149280.1169382564.1682168622.1687178001.1687181253.7; __utmb=30149280.0.10.1687181253; __utmz=30149280.1687181253.7.6.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utma=223695111.1640817040.1683638062.1687178001.1687181253.3; __utmb=223695111.0.10.1687181253; __utmz=223695111.1687181253.3.3.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1687181253%2C%22https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DujFBYcF3-z7ymnUy-5xo5XWpfNzul-nJyXI3inL3u3eedAEiRBhQ-FAXcPdn2OYL%26wd%3D%26eqid%3D836185fc0016dde800000006649057c1%22%5D; _pk_ses.100001.4cf6=1',
'Host': 'movie.douban.com',
'Pragma': 'no-cache',
'Referer': 'https://www.baidu.com/link?url=ujFBYcF3-z7ymnUy-5xo5XWpfNzul-nJyXI3inL3u3eedAEiRBhQ-FAXcPdn2OYL&wd=&eqid=836185fc0016dde800000006649057c1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'cross-site',
'Sec-Fetch-User': '?1',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
'sec-ch-ua': '"Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
}
# headers=headers 携带请求头模拟请求
response = requests.get('https://movie.douban.com/top250', headers=headers)
html_str = response.text
print(html_str)
"""
一般请求被反扒了, 有如下请求头字段, 一般都需要添加
Origin: 声明资源的起始位置
User-Agent: 浏览器的身份标识
Host: 访问的域名
Referer: 防盗链,告诉服务器从哪个页面跳转过来
Cookies: 用户身份标识, 能不加就不加
"""
import requests
headers = {
'Cookie': 'll="118267"; bid=VrC8tT1GWz8; __gads=ID=744f53c3cb2ebb52-22841ef3a4e00021:T=1683638065:RT=1683638065:S=ALNI_MZhRKuML1OBDnNRafe3qd6-ndhaiQ; __gpi=UID=00000c03bafcda5c:T=1683638065:RT=1683638065:S=ALNI_MbkLLsUm467wiS6ZZ6Mn2ohKIWBZw; __yadk_uid=iHqVKZD4ZHIVREbOrlu9k4uWFSsAdZtO; _pk_id.100001.4cf6=b39d476add4f5658.1683638062.; ap_v=0,6.0; __utmc=30149280; __utmc=223695111; __utma=30149280.1169382564.1682168622.1687178001.1687181253.7; __utmb=30149280.0.10.1687181253; __utmz=30149280.1687181253.7.6.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utma=223695111.1640817040.1683638062.1687178001.1687181253.3; __utmb=223695111.0.10.1687181253; __utmz=223695111.1687181253.3.3.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1687181253%2C%22https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DujFBYcF3-z7ymnUy-5xo5XWpfNzul-nJyXI3inL3u3eedAEiRBhQ-FAXcPdn2OYL%26wd%3D%26eqid%3D836185fc0016dde800000006649057c1%22%5D; _pk_ses.100001.4cf6=1',
'Host': 'movie.douban.com',
'Referer': 'https://www.baidu.com/link?url=ujFBYcF3-z7ymnUy-5xo5XWpfNzul-nJyXI3inL3u3eedAEiRBhQ-FAXcPdn2OYL&wd=&eqid=836185fc0016dde800000006649057c1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
}
response = requests.get('https://movie.douban.com/top250', headers=headers)
# html_str = response.text
# print(html_str)
"""查看请求体信息"""
# response.request 查看请求体信息
print(response.request.url) # 查看请求体中 url 地址
print(response.request.headers) # 查看请求体中请求头信息, requests模块在请求时,会自动带上常见的请求字段
print(response.request.method) # 查看请求体中请求方法
import requests
headers = {
'Cookie': 'll="118267"; bid=VrC8tT1GWz8; __gads=ID=744f53c3cb2ebb52-22841ef3a4e00021:T=1683638065:RT=1683638065:S=ALNI_MZhRKuML1OBDnNRafe3qd6-ndhaiQ; __gpi=UID=00000c03bafcda5c:T=1683638065:RT=1683638065:S=ALNI_MbkLLsUm467wiS6ZZ6Mn2ohKIWBZw; __yadk_uid=iHqVKZD4ZHIVREbOrlu9k4uWFSsAdZtO; _pk_id.100001.4cf6=b39d476add4f5658.1683638062.; ap_v=0,6.0; __utmc=30149280; __utmc=223695111; __utma=30149280.1169382564.1682168622.1687178001.1687181253.7; __utmb=30149280.0.10.1687181253; __utmz=30149280.1687181253.7.6.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utma=223695111.1640817040.1683638062.1687178001.1687181253.3; __utmb=223695111.0.10.1687181253; __utmz=223695111.1687181253.3.3.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1687181253%2C%22https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DujFBYcF3-z7ymnUy-5xo5XWpfNzul-nJyXI3inL3u3eedAEiRBhQ-FAXcPdn2OYL%26wd%3D%26eqid%3D836185fc0016dde800000006649057c1%22%5D; _pk_ses.100001.4cf6=1',
'Host': 'movie.douban.com',
'Referer': 'https://www.baidu.com/link?url=ujFBYcF3-z7ymnUy-5xo5XWpfNzul-nJyXI3inL3u3eedAEiRBhQ-FAXcPdn2OYL&wd=&eqid=836185fc0016dde800000006649057c1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
}
response = requests.get('https://movie.douban.com/top250', headers=headers)
# html_str = response.text
# print(html_str)
"""查看响应体信息"""
# response.request 查看请求体信息
"""获取响应体数据"""
print(response.text) # 字符串
print(response.content) # 二进制数据, 图片\视频\音频
# print(response.json()) # json数据, 只有规范的json数据才可以用json方法提取, 不然报错(JSONDecodeError)
print(response.headers) # 查看响应体的响应头信息
print(response.encoding) # 指定响应体编码
print(response.apparent_encoding) # 自动识别响应体编码
print(response.cookies)
print(response.cookies.get_dict()) # RequestsCookieJar 转字典
print(response.url) # 获取响应体的url地址
print(response.status_code) # 获取响应体的状态码
'''
下厨房首页数据爬取(UA检测)
url:https://www.xiachufang.com/
- 爬虫模拟浏览器主要是模拟请求参数和主要的请求头。
- User-Agent:请求载体的身份标识。
- 使用浏览器发请求,则请求载体就是浏览器
- 使用爬虫程序发请求,则请求载体就是爬虫程序
- 反爬机制:UA检测
- 网站后台会检测请求的载体是不是浏览器,如果是则返回正常数据,不是则返回错误数据。
- 反反爬机制:UA伪装
- 将爬虫发起请求的User-Agent伪装成浏览器的身份
'''
import requests
# 请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
# 1.指定url
url = 'https://www.xiachufang.com/'
# 2.发起请求
# 携带了指定的请求头进行的请求发送
response = requests.get(url=url, headers=headers)
# 3.获取响应数据
page_text = response.text
# 4.持久化存储
with open('cook.html', 'w', encoding='utf-8') as fp:
fp.write(page_text)
import requests
response = requests.get('http://www.pcbaby.com.cn/')
## 方式1 :自动识别响应体编码
response.encoding = response.apparent_encoding
# 方式2 :手动指定编码识别
response.encoding = 'gb2312'
html_str = response.text
print(html_str)
网址 :www.json.cn 可以翻译 Json 数据信息
"""json数据"""
# json数据是目前主流的数据交换格式 (结构清晰, 方便取值)
# 形式: 外层 {} [] 包裹 嵌套数据
# {"字段1": "值1",字段2: {嵌套字段1: 嵌套字段值1}, {}, {} ...}
# json数据和字典非常像, 但是有区别, 引号, json数据必须用双引号
"""
在json数据中, 值必须是以下数据类型
字符串
数字
对象(json对象)<嵌套形式>
数组
布尔值
null --> 字符串
"""
import requests
response = requests.get('https://www.ku6.com/video/feed?pageNo=0&pageSize=40&subjectId=72')
print(response.json())
# # 通过 json() 提取json数据之后, 会在底层经过数据转换, 转换成一个对象
print(type(response.json()))
import requests
response = requests.get('https://i.hexuexiao.cn/up/da/75/47/f59543039ce27d69ef5d25b5a04775da.jpg')
# .content --> 提取响应体二进制数据
img_data = response.content
print(img_data)
# 图片\音频\视频
with open('a.jpg', mode='wb') as f:
f.write(img_data)
"""
目标地址:https://m.maoyan.com/asgard/board/4
要求:
1、请求到目标网址数据,需要在请求到的数据中看到当前页面所有的电影名字、主演、上映时间、评分等信息
2、请列举在请求不到数据时,需要添加几个常见请求头字段(课程讲过)
请在下方编写代码
"""
import requests
headers = {
'Cookie': 'iuuid=F5783590DF7F11ED9B25CD5E5234694FA2DAA684142046EEA9F6AB456B2AFF02; _lxsdk_cuid=1879ededf23c8-0483e83e302f2e-26031b51-1fa400-1879ededf23c8; _lxsdk=F5783590DF7F11ED9B25CD5E5234694FA2DAA684142046EEA9F6AB456B2AFF02; ci=70%2C%E9%95%BF%E6%B2%99; ci.sig=6ddYdqOybjnPiJJMwTWmS44rF4o; ci=70%2C%E9%95%BF%E6%B2%99; ci.sig=6ddYdqOybjnPiJJMwTWmS44rF4o; ci=70%2C%E9%95%BF%E6%B2%99; ci.sig=6ddYdqOybjnPiJJMwTWmS44rF4o; _lxsdk_s=188ddc29cb4-793-726-aed%7C%7CNaN; Hm_lvt_703e94591e87be68cc8da0da7cbd0be2=1687347699; Hm_lpvt_703e94591e87be68cc8da0da7cbd0be2=1687347699',
'Host': 'm.maoyan.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
# headers=headers 在请求的时候携带请求头伪装
response = requests.get('https://m.maoyan.com/asgard/board/4', headers=headers)
response.encoding = response.apparent_encoding
print(response.text)
"""
User-Agent: 浏览器的身份标识
Host: 访问服务器的域名
referer: 防盗链,告诉服务器此次请求是从哪个页面跳转过来的
origin: 资源地址的地址位置
cookies: 用户身份字段
"""
"""
目标网址:https://www.ku6.com/video/feed?pageNo=0&pageSize=40&subjectId=76
发送 GET 请求
要求:
1、请求上述网址的数据
2、按照要求提取以下字段信息
title、
picPath、
playUrl
提取下来用 print() 函数打印即可
请在下方编写代码
"""
import pprint
import requests
response = requests.get('https://www.ku6.com/video/feed?pageNo=0&pageSize=40&subjectId=76')
json_data = response.json()
print(json_data)
# pprint.pprint(json_data)
for res in json_data['data']:
title = res['title']
picPath = res['picPath']
playUrl = res['playUrl']
print(title, picPath, playUrl)
"""
目标网址:https://ibaotu.com/sucai/19838349.html
要求:
1、在上述目标网址中找到视频的数据包
2、用requests模块模拟请求视频数据并且保存下来
请在下方编写代码
"""
import requests
url = 'https://video-qn.ibaotu.com/19/83/83/49Z888piC4I8.mp4'
response = requests.get(url)
video_data = response.content
file_name = url.split('/')[-1]
# 准备保存视频的文件名字
with open(file_name, mode='wb') as f:
f.write(video_data)
requests 模块允许你使用 params 关键字参数,以一个字典来提供这些参数。
举例来说,如果你想传递 key1=value1 和 key2=value2 到 httpbin.org/get ,那么你可以使用如下代码:
import requests
params = {'q': '风景', 'src': 'srp'}
response = requests.get("https://image.so.com/i", params=params)
# 通过打印输出该 URL,你能看到 URL 已被正确编码:
print(response.url)
# 打印结果
https://image.so.com/i?q=%E9%A3%8E%E6%99%AF&src=srp
在url地址中默认是不支持中文字符的,所以在请求中会把中文字符转化成url编码形式
同样的查询参数可以在浏览器抓包工具中找到,位于Headers栏目下的Query String Parameters中,如下图所示:
import requests
headers = {
'Cookie': 'iuuid=F5783590DF7F11ED9B25CD5E5234694FA2DAA684142046EEA9F6AB456B2AFF02; _lxsdk_cuid=1879ededf23c8-0483e83e302f2e-26031b51-1fa400-1879ededf23c8; _lxsdk=F5783590DF7F11ED9B25CD5E5234694FA2DAA684142046EEA9F6AB456B2AFF02; ci=70%2C%E9%95%BF%E6%B2%99; ci.sig=6ddYdqOybjnPiJJMwTWmS44rF4o; ci=70%2C%E9%95%BF%E6%B2%99; ci.sig=6ddYdqOybjnPiJJMwTWmS44rF4o; ci=70%2C%E9%95%BF%E6%B2%99; ci.sig=6ddYdqOybjnPiJJMwTWmS44rF4o; _lxsdk_s=188ddc29cb4-793-726-aed%7C%7CNaN; Hm_lvt_703e94591e87be68cc8da0da7cbd0be2=1687347699; Hm_lpvt_703e94591e87be68cc8da0da7cbd0be2=1687347699',
'Host': 'm.maoyan.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
response = requests.get(url='https://m.maoyan.com/asgard/board/4', headers=headers)
print(response.url)
"""
method: 请求方法 get post
url: 请求网址的关键字
params: (可选参数) 指定查询参数
data: (可选参数) 指定请求参数
json: (可选参数) 指定json数据形式发送请求
headers: (可选参数) 请求头关键字参数
cookies: (可选参数) 请求的时候指定用户身份标识
proxies: (可选参数) 使用代理请求的关键字
timeout: (可选参数) 指定请求的时间, 单位/秒
allow_redirects: (可选参数) 是否允许重定向, 300左右
verify: (可选参数) 控制是否验证网站证书
files: (可选参数) 上传文件
auth: (可选参数) 权限认证
stream: (可选参数) 是否是数据流传输的数据
"""
查询参数
和 请求参数
。当我们爬一些特殊网址时,请求的url中会有一些特殊的参数,例如以下站点:
这种是 URL 的查询参数。前面是网址,? 后面的二值性数据,就是查询参数。
URL 的查询字符串(query string)传递某种数据。如果你是手工构建 URL,也就是通过拼接字符串构造的URL。那么数据会以键/值对的形式置于 URL 中,跟在一个问号的后面。
例如:
https://image.so.com/i?q=%E9%A3%8E%E6%99%AF&src=srp
# https://pic.sogou.com/pics?query=%E8%9C%A1%E7%AC%94%E5%B0%8F%E6%96%B0&mood=7&dm=0&mode=1
"""
查询参数:
在地址中如果与查询参数, 那么就是?后面的部分, 是属于查询参数
? 前面是请求地址, 后面是一系列的查询参数
& 隔开每一个查询参数
所有查询参数都是二值型的数据, key=value
"""
import requests
url = 'https://pic.sogou.com/pics?'
params = {
'query': '蜡笔小新',
'mood': '7',
'dm': '0',
'mode': '1'
}
# params 指定查询参数
# ? 可加可不加
response = requests.get(url=url, params=params)
print(response.request.url)
# https://pic.sogou.com/pics?query=%E8%9C%A1%E7%AC%94%E5%B0%8F%E6%96%B0&mood=7&dm=0&mode=1
"""
在http协议中, 默认不支持中文编码, 如果请求地址中包含中文, 会自动进行url编码
url编码: 由 % + 数字 + 字母
"""
# 手动转化url编码
# requests.utils.quote 对中文进行url编码
print(requests.utils.quote('蜡笔小新'))
# requests.utils.unquote 对中文进行url解码
print(requests.utils.unquote('%E8%9C%A1%E7%AC%94%E5%B0%8F%E6%96%B0'))
''' 示例1 - 51游戏搜索 '''
# 注意:在浏览器的地址栏中网址,网址?后面的内容就是请求的参数(请求参数)
import requests
# 1.指定url
params = { # 字典是用于封装请求参数
'q': '传奇'
}
url = 'https://game.51.com/search/action/game/'
# 2.发起请求
# get是基于指定的url和携带了固定的请求参数进行请求发送
response = requests.get(url=url, params=params)
# 3.获取响应数据
page_text = response.text # text表示获取字符串形式的响应数据
# print(page_text)
# 4.持久化存储
with open('传奇.html', 'w', encoding='utf-8') as fp:
fp.write(page_text)
''' 示例2 - 51游戏中任何游戏对应的搜索结果页面数据 '''
import requests
# 1.指定url
game_title = input('enter a game name:')
params = { # 字典是用于封装请求参数
'q': game_title
}
url = 'https://game.51.com/search/action/game/'
# 2.发起请求
# get是基于指定的url和携带了固定的请求参数进行请求发送
response = requests.get(url=url, params=params)
# 3.获取响应数据
page_text = response.text # text表示获取字符串形式的响应数据
# print(page_text)
# 4.持久化存储
fileName = game_title + '.html'
with open(fileName, 'w', encoding='utf-8') as fp:
fp.write(page_text)
'''
通过抓包工具的分析发现,搜索菜谱的数据包有两个请求参数:
- keyword:搜索的关键字
- cat:1001固定形式
'''
import requests
# 请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
title = input('请输入菜名:')
# 请求参数
params = {
'keyword': title,
'cat': '1001'
}
# 1.指定url
url = 'https://www.xiachufang.com/search/'
# 2.发起请求
response = requests.get(url=url, headers=headers, params=params)
# 处理乱码
response.encoding = 'utf-8' # gbk
# 3.获取响应数据
page_text = response.text
# 4.持久化存储
fileName = title + '.html'
with open(fileName, 'w', encoding='utf-8') as fp:
fp.write(page_text)
'''
爬取网址 :https://movie.douban.com/typerank?type_name=%E7%88%B1%E6%83%85&type=13&interval_id=100:90&action=
将豆瓣电影中的电影名称和电影的评分进行爬取
测试:直接使用浏览器地址栏中的url,进行请求发送查看是否可以爬取到电影详情数据?
'''
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
url = 'https://movie.douban.com/typerank?type_name=%E7%88%B1%E6%83%85&type=13&interval_id=100:90&action='
response = requests.get(url=url, headers=headers)
page_text = response.text
with open('douban.html', 'w') as fp:
fp.write(page_text)
经过测试发现,我们爬取到的数据并没有包含电影详情数据,why?
'''
- 在一个网页中看到的数据,并不一定是通过浏览器地址栏中的url发起请求请求到的。如果请求不到,一定是基于其他的请求请求到的数据。
- 动态加载数据值的就是:
不是直接通过浏览器地址栏的url请求到的数据,这些数据叫做动态加载数据。
- 如何获取动态加载数据?
- 确定动态加载的数据是基于哪一个数据包请求到的?
- 数据包数据的全局搜索:
- 点击抓包工具中任何一个数据包
- control+f进行全局搜索(弹出全局搜索框)
- 目的:定位动态加载数据是在哪一个数据包中
- 定位到动态加载数据对应的数据包,模拟该数据包进行请求发送即可:
- 从数据包中提取出:
- url
- 请求参数
'''
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
params = {
"type": "13",
"interval_id": "100:90",
"action": "",
"start": "0",
"limit": "20"
}
url = 'https://movie.douban.com/j/chart/top_list'
response = requests.get(url=url, headers=headers, params=params)
# json()可以获取json格式的响应数据,并且直接对json格式的响应数据进行反序列化
data_list = response.json()
fp = open('movie.txt', 'w')
for dic in data_list:
title = dic['title']
score = dic['score']
print(title, score)
fp.write(title + ':' + score + '\n')
fp.close()
"""
ajax 异步加载
在不加载整个网页的情况下, 对页面进行局部刷新
页面上半部分数据不会刷新, 下半部分加载新数据
网站动态数据渲染:
页面第一页数据做了静态数据渲染
后续页数的数据统一做动态渲染
一般情况下可以按照动态数据包翻页的规律, 构建第一页请求
"""
import requests
def get_params(page):
"""构建请求参数的函数"""
return {
'mood': '7',
'dm': '0',
'mode': '1',
'start': str(page),
'xml_len': '48',
'query': '蜡笔小新'
}
url = 'https://pic.sogou.com/napi/pc/searchList'
for i in range(0, 97, 48):
# print(i)
params = get_params(i)
response = requests.get(url=url, params=params)
json_data = response.json()
list_data = json_data['data']['items']
for data in list_data:
img_url = data['picUrl']
print(img_url)
import requests
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx'
params = {'op': 'keyword'} # 查询参数
data = { # 请求参数
'cname': '',
'pid': '',
'keyword': '北京',
'pageIndex': '1',
'pageSize': '10'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'}
# data是构建post请求的请求参数关键字
response = requests.post(url=url, params=params, data=data, headers=headers)
json_data = response.json()
print(json_data)
list_data = json_data['Table1']
for res in list_data:
storeName = res['storeName']
addressDetail = res['addressDetail']
pro = res['pro']
print(storeName, addressDetail, pro)
"""
注意事项:
1. 浏览器中地址导航栏只能发送get请求
2. post请求还会有另一种请求参数<Form Data> 和 <Request Payload> --> 以json数据提交的请求参数, 用json关键字传递
"""
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
for page in range(1, 6):
data = {
"cname": "",
"pid": "",
"keyword": "天津",
"pageIndex": str(page), # 设置打印页数
"pageSize": "10"
}
# post请求携带请求参数使用data这个参数
response = requests.post(url=url, headers=headers, data=data)
data = response.json()
for dic in data['Table1']:
city = dic['cityName']
address = dic['addressDetail']
print(city, address)
# 方式1:
import requests
url = 'https://img0.baidu.com/it/u=540025525,3089532369&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500'
response = requests.get(url=url)
# content获取二进制形式的响应数据
img_data = response.content
with open('1.jpg', 'wb') as fp:
fp.write(img_data)
# 方式2
from urllib import request
url = 'https://img0.baidu.com/it/u=540025525,3089532369&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500'
# urlretrieve可以将参数1表示的图片地址请求并且保存到参数2的目录中
request.urlretrieve(url, '2.jpg')
#### 爬取图片的时候需要做UA伪装使用方式1,否则使用方式2 ####
requests模块中发送POST请求也是比较容易的操作,要实现这个,只需简单地传递一个字典给data参数。你的数据字典在发出请求时会自动编码为表单形式:
data = {'key1': 'value1', 'key2': 'value2'}
response = requests.post("http://httpbin.org/post", data=data)
当然Requests中的post方法只是相对于get方法多了一个data参数,其他参数都是类似的,例如我们也可以为post中的网址添加查询字符串 params 参数,也可以像get方法一样添加 headers 参数等。
学习http协议的时候,请求体字段中就讲述过cookies字段,这个字段代表用户身份的标识,一般平台通过这个字段存储用户信息,包括并不限于用户名、密码、登陆时间等等。一般cookies信息都是二值型的,即key=value形式,非常像字典的构造形式。每一个key=value的信息,都代表用户的片段信息,很多个key=value片段构成一个完整的cookies字段,如下图所示:
import requests
url = 'https://fanyi.baidu.com/v2transapi?from=zh&to=en'
headers = {
'Acs-Token': '1687354513445_1687354530324_U0QUCd0KA/F7BYp74tXcgnoFsNtOOxo4iufv+Hk5xXqn2+frnr0XUBVQuvTA3dfcUNYPfwpE/Y/JKtFNRsVrPchR4jO1sLxlmyw0hvh3usx51exIBKNRgH4NQXBDqAt3YJadXkNDjTR67nCTZiw+RJk7dF5HUYF5tJQ2b6P7MOd74rkMTn+xiwSraonXITV1rfLX6Pljrf7BCAACg8KuPEJplI1HlqnRHpoq54OKlcGiWXm2ZWfAcq4EVmqb1nVSge61u6U85j/n7R3JJ4LA96Vw0kcKtFi5X8GAw2SHCZ1fAZREBFeYdhG6fXVEZP+e6mkHJn/yUmb3IUb+GxtEhS1alaQMFv9QQZSBx6tXbfW6ncLHgcZfcDTqoKWSe3tdX39s1qnOEoWGvwLFFe/XMszJzUdMuOhndbQPdjkofy58aIlMTJErOTeELJ+21UOigR2VuwxiD/k9oI7vmMH0UUYzjVqojZcGNU2GrWMcfto=',
# 'Cookie': "BIDUPSID=A8D9EA340531252B16551CBD43A8D395; PSTM=1681976911; BAIDUID=A8D9EA340531252BDEF2C13A73AFA5E7:FG=1; APPGUIDE_10_0_2=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; H_WISE_SIDS=131862_114552_216844_213346_214803_219942_110085_243887_244712_249892_256348_256447_256739_254317_257586_257996_258372_258375_230288_259102_259287_258772_234207_234295_253022_260335_260806_259299_253631_261575_261718_261459_261983_259782_260440_261793_259629_236312_262490_262452_261869_262607_262677_262597_262604_249411_259519_259948_262743_262746_262913_263190_256998_263221_263306_263279_243615_263343_261683_263434_254299_261411_263584_257289_262439_262533_263644_262408_262910_257169_262289_263906_263363_256419_264175_264089_264228_257442_256225_262260_255224_264018_264368_259558_256083_264383_264423_264452_264285_256152_264626_264246_258698_264749_261934_264820_264136_261035_261663; H_PS_PSSID=38516_36550_38686_38860_38793_38841_38581_38802_38828_38840_38640_26350; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BAIDUID_BFESS=A8D9EA340531252BDEF2C13A73AFA5E7:FG=1; delPer=0; PSINO=6; BA_HECTOR=ah2g2ka48k0g8h2h00a4842h1i95r4t1p; ZFY=CMMricp5SfogOfi1RswFaP4NBZN6t5zy:Axurblw8al4:C; BCLID=8504214758825411246; BCLID_BFESS=8504214758825411246; BDSFRCVID=TO8OJexroG0ZmSbfuwStIGta5LweG7bTDYrEOwXPsp3LGJLVFakFEG0Pts1-dEu-S2OOogKKLmOTHpKF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; BDSFRCVID_BFESS=TO8OJexroG0ZmSbfuwStIGta5LweG7bTDYrEOwXPsp3LGJLVFakFEG0Pts1-dEu-S2OOogKKLmOTHpKF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tRAOoC_-tDvDqTrP-trf5DCShUFsLU4OB2Q-XPoO3KJADfOPbRob0n0PQpOKtx7f5mkf3fbgy4op8P3y0bb2DUA1y4vp0toW3eTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPr9QgbjahQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHjDMDTJy3j; H_BDCLCKID_SF_BFESS=tRAOoC_-tDvDqTrP-trf5DCShUFsLU4OB2Q-XPoO3KJADfOPbRob0n0PQpOKtx7f5mkf3fbgy4op8P3y0bb2DUA1y4vp0toW3eTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPr9QgbjahQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHjDMDTJy3j; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1687354513; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1687354513; ab_sr=1.0.1_NDJjZTI3ZGQwZjJhN2I2YThjMWMxNDgxNWJhOGM5YTEwMjYwYWM0NDU3Mjk0Y2MxZTAyNWE0MzIyNDlhYjJmYjQ5NDUxNzEzOTI4YmIyZjUyNDFiNjFkM2Q0ZTYyMjZjMGU1ZTU3MDFiMTNhMWU5NTY2NDdlYWExZWEyZDZiMWNkNGVjMTExNTQyM2MyNzYxYThiNzAzYmUxNTAxZGI2NA==",
'Host': 'fanyi.baidu.com',
'Origin': 'https://fanyi.baidu.com',
'Referer': 'https://fanyi.baidu.com/?aldtype=16047',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
data = {
'from': 'zh',
'to': 'en',
'query': '你好',
'transtype': 'realtime',
'simple_means_flag': '3',
'sign': '232427.485594',
'token': '351b986af9e8a703056ff2f022cdf830',
'domain': 'common',
'ts': '1687354530307',
}
# cookies = {'Cookie': 'BIDUPSID=A8D9EA340531252B16551CBD43A8D395; PSTM=1681976911; BAIDUID=A8D9EA340531252BDEF2C13A73AFA5E7:FG=1; APPGUIDE_10_0_2=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; H_WISE_SIDS=131862_114552_216844_213346_214803_219942_110085_243887_244712_249892_256348_256447_256739_254317_257586_257996_258372_258375_230288_259102_259287_258772_234207_234295_253022_260335_260806_259299_253631_261575_261718_261459_261983_259782_260440_261793_259629_236312_262490_262452_261869_262607_262677_262597_262604_249411_259519_259948_262743_262746_262913_263190_256998_263221_263306_263279_243615_263343_261683_263434_254299_261411_263584_257289_262439_262533_263644_262408_262910_257169_262289_263906_263363_256419_264175_264089_264228_257442_256225_262260_255224_264018_264368_259558_256083_264383_264423_264452_264285_256152_264626_264246_258698_264749_261934_264820_264136_261035_261663; H_PS_PSSID=38516_36550_38686_38860_38793_38841_38581_38802_38828_38840_38640_26350; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BAIDUID_BFESS=A8D9EA340531252BDEF2C13A73AFA5E7:FG=1; delPer=0; PSINO=6; BA_HECTOR=ah2g2ka48k0g8h2h00a4842h1i95r4t1p; ZFY=CMMricp5SfogOfi1RswFaP4NBZN6t5zy:Axurblw8al4:C; BCLID=8504214758825411246; BCLID_BFESS=8504214758825411246; BDSFRCVID=TO8OJexroG0ZmSbfuwStIGta5LweG7bTDYrEOwXPsp3LGJLVFakFEG0Pts1-dEu-S2OOogKKLmOTHpKF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; BDSFRCVID_BFESS=TO8OJexroG0ZmSbfuwStIGta5LweG7bTDYrEOwXPsp3LGJLVFakFEG0Pts1-dEu-S2OOogKKLmOTHpKF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tRAOoC_-tDvDqTrP-trf5DCShUFsLU4OB2Q-XPoO3KJADfOPbRob0n0PQpOKtx7f5mkf3fbgy4op8P3y0bb2DUA1y4vp0toW3eTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPr9QgbjahQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHjDMDTJy3j; H_BDCLCKID_SF_BFESS=tRAOoC_-tDvDqTrP-trf5DCShUFsLU4OB2Q-XPoO3KJADfOPbRob0n0PQpOKtx7f5mkf3fbgy4op8P3y0bb2DUA1y4vp0toW3eTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPr9QgbjahQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHjDMDTJy3j; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1687354513; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1687354513; ab_sr=1.0.1_NDJjZTI3ZGQwZjJhN2I2YThjMWMxNDgxNWJhOGM5YTEwMjYwYWM0NDU3Mjk0Y2MxZTAyNWE0MzIyNDlhYjJmYjQ5NDUxNzEzOTI4YmIyZjUyNDFiNjFkM2Q0ZTYyMjZjMGU1ZTU3MDFiMTNhMWU5NTY2NDdlYWExZWEyZDZiMWNkNGVjMTExNTQyM2MyNzYxYThiNzAzYmUxNTAxZGI2NA=='}
# 将每个cookies片段构建键值对
cookies = {
'BAIDUID': 'A8D9EA340531252BDEF2C13A73AFA5E7:FG=1',
'BAIDUID_BFESS': 'A8D9EA340531252BDEF2C13A73AFA5E7:FG=1',
'ZFY': 'CMMricp5SfogOfi1RswFaP4NBZN6t5zy:Axurblw8al4:C',
'BIDUPSID': 'A8D9EA340531252B16551CBD43A8D395',
'PSTM': '1681976911',
'APPGUIDE_10_0_2': '1',
'REALTIME_TRANS_SWITCH': '1',
'FANYI_WORD_SWITCH': '1',
'HISTORY_SWITCH': '1',
'SOUND_SPD_SWITCH': '1',
'SOUND_PREFER_SWITCH': '1',
'H_WISE_SIDS': '131862_114552_216844_213346_214803_219942_110085_243887_244712_249892_256348_256447_256739_254317_257586_257996_258372_258375_230288_259102_259287_258772_234207_234295_253022_260335_260806_259299_253631_261575_261718_261459_261983_259782_260440_261793_259629_236312_262490_262452_261869_262607_262677_262597_262604_249411_259519_259948_262743_262746_262913_263190_256998_263221_263306_263279_243615_263343_261683_263434_254299_261411_263584_257289_262439_262533_263644_262408_262910_257169_262289_263906_263363_256419_264175_264089_264228_257442_256225_262260_255224_264018_264368_259558_256083_264383_264423_264452_264285_256152_264626_264246_258698_264749_261934_264820_264136_261035_261663',
'H_PS_PSSID': '38516_36550_38686_38860_38793_38841_38581_38802_38828_38840_38640_26350',
'BDORZ': 'B490B5EBF6F3CD402E515D22BCDA1598',
'delPer': '0',
'PSINO': '6',
'BA_HECTOR': 'ah2g2ka48k0g8h2h00a4842h1i95r4t1p',
'BCLID': '8504214758825411246',
'BCLID_BFESS': '8504214758825411246',
'BDSFRCVID': 'TO8OJexroG0ZmSbfuwStIGta5LweG7bTDYrEOwXPsp3LGJLVFakFEG0Pts1-dEu-S2OOogKKLmOTHpKF_2uxOjjg8UtVJeC6EG0Ptf8g0M5',
'BDSFRCVID_BFESS': 'TO8OJexroG0ZmSbfuwStIGta5LweG7bTDYrEOwXPsp3LGJLVFakFEG0Pts1-dEu-S2OOogKKLmOTHpKF_2uxOjjg8UtVJeC6EG0Ptf8g0M5',
'H_BDCLCKID_SF': 'tRAOoC_-tDvDqTrP-trf5DCShUFsLU4OB2Q-XPoO3KJADfOPbRob0n0PQpOKtx7f5mkf3fbgy4op8P3y0bb2DUA1y4vp0toW3eTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPr9QgbjahQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHjDMDTJy3j',
'H_BDCLCKID_SF_BFESS': 'tRAOoC_-tDvDqTrP-trf5DCShUFsLU4OB2Q-XPoO3KJADfOPbRob0n0PQpOKtx7f5mkf3fbgy4op8P3y0bb2DUA1y4vp0toW3eTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPr9QgbjahQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHjDMDTJy3j',
'Hm_lvt_64ecd82404c51e03dc91cb9e8c025574': '1687354513',
'Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574': '1687354513',
'ab_sr': '1.0.1_NDJjZTI3ZGQwZjJhN2I2YThjMWMxNDgxNWJhOGM5YTEwMjYwYWM0NDU3Mjk0Y2MxZTAyNWE0MzIyNDlhYjJmYjQ5NDUxNzEzOTI4YmIyZjUyNDFiNjFkM2Q0ZTYyMjZjMGU1ZTU3MDFiMTNhMWU5NTY2NDdlYWExZWEyZDZiMWNkNGVjMTExNTQyM2MyNzYxYThiNzAzYmUxNTAxZGI2NA==',
}
# cookies关键字
response = requests.post(url=url, data=data, headers=headers, cookies=cookies)
json_data = response.json()
print(json_data)
# 请求会校验用户cookies字段
"""
携带cookies的方式:
1. 放到请求头里面
2. 可以通过构建cookies字典用cookies关键字请求
3. 将cookies的每一个片段信息构建键值对, 通过cookies关键字请求
"""
当用户通过浏览器首次访问一个域名时,访问的web服务器会给客户端发送数据,以保持web服务器与客户端之间的状态保持,这些数据就是cookie,它是Internet站点创建的,为了辨别用户身份而储存在用户本地终端上的数据,cookie大部分都是加密的,cookie存在与缓存中或者硬盘中,在硬盘中的是一些文本文件,当你访问该网站时,就会读取对应的网站的cookie信息,cookie有效地提升了用户体验,一般来说,一旦将cookie保存在计算机上,则只有创建该cookie的网站才能读取它
大家都知道HTTP协议是无状态的。
记住:cookie表示的键值对数据是由服务器创建,且存储在客户端浏览器中。
cookie的工作原理是:
'''
- url:https://xueqiu.com/,需求就是爬取热帖内容
- 经过分析发现帖子的内容是通过ajax动态加载出来的,因此通过抓包工具,定位到ajax请求的数据包,从数据包中提取:
- url:https://xueqiu.com/statuses/hot/listV2.json?since_id=-1&max_id=311519&size=15
- 请求方式:get
- 请求参数:拼接在了url后面
'''
import requests
import os
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36',
}
url = 'https://xueqiu.com/statuses/hot/listV2.json'
param = {
"since_id": "-1",
"max_id": "311519",
"size": "15",
}
response = requests.get(url=url, headers=headers, params=param)
data = response.json()
print(data)
#### 发现没有拿到我们想要的数据 ####
'''
- 分析why?
- 切记:只要爬虫拿不到你想要的数据,唯一的原因是爬虫程序模拟浏览器的力度不够!一般来讲,模拟的力度重点放置在请求头中!
- 上述案例,只需要在请求头headers中添加cookie即可!
- 爬虫中cookie的处理方式(两种方式):
- 手动处理:将抓包工具中的cookie赋值到headers中即可
- 缺点:
- 编写麻烦
- cookie通常都会存在有效时长
- cookie中可能会存在实时变化的局部数据
- 自动处理
- 基于session对象实现自动处理cookie。
- 1.创建一个空白的session对象。
- 2.需要使用session对象发起请求,请求的目的是为了捕获cookie
- 注意:如果session对象在发请求的过程中,服务器端产生了cookie,则cookie会自动存储在session对象中。
- 3.使用携带cookie的session对象,对目的网址发起请求,就可以实现携带cookie的请求发送,从而获取想要的数据。
- 注意:session对象至少需要发起两次请求
- 第一次请求的目的是为了捕获存储cookie到session对象
- 后次的请求,就是携带cookie发起的请求了
'''
import requests
# 1.创建一个空白的session对象
session = requests.Session()
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36',
}
main_url = 'https://xueqiu.com/'
# 2.使用session发起的请求,目的是为了捕获到cookie,且将其存储到session对象中
session.get(url=main_url, headers=headers)
url = 'https://xueqiu.com/statuses/hot/listV2.json'
param = {
"since_id": "-1",
"max_id": "311519",
"size": "15",
}
# 3.就是使用携带了cookie的session对象发起的请求(就是携带者cookie发起的请求)
response = session.get(url=url, headers=headers, params=param)
data = response.json()
print(data)
#### 获取https://passport.17k.com/中的书架页面里的图书信息 ####
import pprint
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
}
# 发送登陆处理接口的url地址
url = 'https://passport.17k.com/ck/user/login'
# 传递给服务器端的数据
data = {
'loginName': '15027900535',
'password': 'bobo328410948'
}
session = requests.Session()
response = session.post(url, headers=headers, data=data)
pprint.pprint(response.text)
# 抓取登录后的数据:书架页面
# url = 'https://user.17k.com/www/bookshelf/'
# 书架页面的图书信息
url = 'https://user.17k.com/ck/author/shelf?page=1&appKey=2406394919'
res = session.get(url, headers=headers)
# 获取书架上的所有书籍
shelf_books = res.json()
pprint.pprint(shelf_books)
数字证书(俗称ca证书,以下简称ca证书)
为实现双方安全通信提供了电子认证。在因特网、公司内部网或外部网中,使用数字证书实现身份识别和电子信息加密。数字证书中含有密钥对(公钥和私钥)所有者的识别信息,通过验证识别信息的真伪实现对证书持有者身份的认证。如果出现上述错误,那么我们可以用verify关键字参数,在请求的时候不验证网站的ca证书
response = requests.get("url", verify=False)
如果加了verify=False这个关键字参数,使用requests模块发送请求的时候会给你弹出一个警告,警告你当前的请求可能不安全,如下图所示:
这个警告对于后面的代码逻辑没有影响,有强迫症的可以考虑加入以下代码忽略警告:
import requests
import urllib3
# urllib3.disable_warnings() # 忽略关闭认证ca证书之后引发的警告
requests.packages.urllib3.disable_warnings()
url = 'https://data.stats.gov.cn/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
# verify=False 使用requests模块发送请求的时候,不验证ca证书,默认会验证(verify=True)
response = requests.post(url=url, headers=headers, verify=False)
data = response.text
print(data)
"""
网站没有证书使用requests模块请求会报错 --> requests.exceptions.SSLError
"""
如果对于requests模块发送的网络请求,请求数据的速度太慢,达不到你的要求。那么你可以考虑加上timeout关键字参数对于请求数据的时间做出限制,如下所示:
import requests
url = 'https://www.baidu.com/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
# timeout 设置一个请求获取数据的时间, 如果超过这个时间就会报错, 报错可以用异常捕获解决
response = requests.get(url=url, headers=headers, timeout=2)
data = response.text
print(data)
# 限制时间单位以秒为单位,超过这个时间限制,程序报错。对于报错可以用异常捕获解决。
对于一些重定向的网络请求,比如登陆成功后跳转到用户个人页面。如果对于当前请求你不想要重定向,就需要当前地址数据,那么可以添加allow_redirects=False关键字,阻止当前请求的重定向。如下所示:
import requests
url = 'http://github.com/'
# allow_redirects默认是True, 自动重定向; 如果设置为False, 那么会阻止重定向
response = requests.get(url=url, allow_redirects=False)
print(response.request.url)
什么是代理
代理服务器的作用
做爬虫的过程中经常会遇到这样的情况:最初爬虫正常运行,正常抓取数据,然而一杯茶的功夫可能就会出现错误,比如403 Forbidden;这时候网页上可能会出现 “您的IP访问频率太高”这样的提示,过很久之后才可能解封,但是一会后又出现这种情况。
造成这种现象的原因是该网站已采取了一些防爬虫措施。 例如,服务器将在一个时间单位内检测IP请求的数量。 如果超过某个阈值,服务器将直接拒绝该服务并返回一些错误信息。 这种情况可以称为封IP,因此该网站成功禁止了我们的抓取工具。
想象一下,由于服务器检测到IP单位时间内的请求数量,因此我们使用某种方式来伪装IP,以使服务器无法识别由本地计算机发起的请求,因此我们可以成功地阻止IP被封。
对应的在使用requests模块发送网络请求时,可以用proxies关键字参数对本地计算机进行伪装,如下所示:
import requests
def get_proxy():
json_data = requests.get('http://demo.spiderpy.cn/get/').json()
proxy = json_data['proxy']
print('获取到的代理:', proxy)
"""
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
"""
proxies = {
"http": "http://" + proxy,
"https": "http://" + proxy,
}
print('规整好的代理:', proxies)
return proxies
# get_proxy()
url = 'https://www.baidu.com/'
proxies = get_proxy()
# 找了一个第三方工具人帮助我们发送请求, 得到数据, 常用于自己电脑ip被服务器封锁的情况
response = requests.get(url=url, proxies=proxies)
print(response.text)
# 代理质量不高会报错: requests.exceptions.ProxyError, 免费代理质量不高, 经常报错, 后面我们会学习付费代理
在爬虫中为何需要使用代理?
代理的匿名度
代理的类型(重要)
如何获取代理?
如何使用代理?
#### 测试:访问如下网址,返回自己本机ip ####
import requests
from lxml import etree
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36',
}
url = 'http://www.cip.cc/'
page_text = requests.get(url, headers=headers).text
tree = etree.HTML(page_text)
text = tree.xpath('/html/body/div/div/div[3]/pre/text()')[0]
print(text.split('\n')[0])
#### 使用代理发起请求,查看是否可以返回代理服务器的ip ####
import requests
from lxml import etree
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36',
}
url = 'http://www.cip.cc/'
page_text = requests.get(url, headers=headers, proxies={'http':'121.234.12.62:4246'}).text
tree = etree.HTML(page_text)
text = tree.xpath('/html/body/div/div/div[3]/pre/text()')[0]
print(text.split('\n')[0])
'''
- 拉勾网一次只能请求5页数据https://www.lagou.com/
- 对快代理进行n次请求,直到本机无法访问快代理为止(证明本机ip被快代理封掉了)
- 构建一个代理池(封装了很多代理ip和端口的容器),用于数据的批量爬取
'''
import requests
from lxml import etree
import random
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36',
}
# 构建一个代理池
proxy_list = []
proxy_url = 'http://webapi.http.zhimacangku.com/getip?num=5&type=3&pro=&city=0&yys=0&port=1&pack=218090&ts=0&ys=0&cs=0&lb=1&sb=0&pb=4&mr=1®ions='
page_text = requests.get(url=proxy_url, headers=headers).text
for ip in page_text.strip().split('\n'):
dic = {}
dic['https'] = ip.strip()
proxy_list.append(dic)
for page in range(1, 5001):
print('正在爬取第%d页的ip数据......' % page)
url = 'https://www.kuaidaili.com/free/inha/%d/' % page
page_text = requests.get(url=url, headers=headers, proxies=random.choice(proxy_list)).text
tree = etree.HTML(page_text)
tr_list = tree.xpath('//*[@id="list"]/table/tbody/tr')
for tr in tr_list:
ip = tr.xpath('./td[1]/text()')[0]
print(ip)
现在很多网站启用了防盗链反爬,防止服务器上的资源被人恶意盗取。什么是防盗链呢?
url:
https://sc.chinaz.com/tupian/meinvtupian.htmlurl:
http://blog.sina.com.cn/lm/pic/,将页面中某一组系列详情页的图片进行抓取保存,比如三里屯时尚女郎:http://blog.sina.com.cn/s/blog_01ebcb8a0102zi2o.html?tj=1
注意:
import requests
from lxml import etree
import os
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
"Referer": "http://blog.sina.com.cn/",
}
url = 'http://blog.sina.com.cn/s/blog_01ebcb8a0102zi2o.html?tj=1'
page_text = requests.get(url, headers=headers).text
tree = etree.HTML(page_text)
img_src = tree.xpath('//*[@id="sina_keyword_ad_area2"]/div/a/img/@real_src')
if not os.path.exists('图片'):
os.mkdir('图片')
img_name = 1
print(img_src)
for src in img_src:
data = requests.get(src, headers=headers).content
with open('./图片/' + str(img_name) + '.jpg', 'wb') as fp:
fp.write(data)
img_name += 1
# break
以下是requests模块中文文档和在GitHub上面的地址:
中文文档:
https://requests.readthedocs.io/projects/cn/zh_CN/latest/
github地址:https://github.com/requests/requests
"""
- 课上的搜狗图片案例,先自己实现一遍, 构建查询参数请求数据
- 将前三页的图片数据保存到文件夹里面
有错误需要解决报错<可以根据情况使用(异常捕获 + 请求参数)>
请在下方编写代码
"""
"""
ajax 异步加载
在不加载整个网页的情况下, 对页面进行局部刷新
页面上半部分数据不会刷新, 下半部分加载新数据
网站动态数据渲染:
页面第一页数据做了静态数据渲染
后续页数的数据统一做动态渲染
一般情况下可以按照动态数据包翻页的规律, 构建第一页请求
"""
import requests
def get_params(page):
"""构建请求参数的函数"""
return {
'mood': '7',
'dm': '0',
'mode': '1',
'start': str(page),
'xml_len': '48',
'query': '蜡笔小新'
}
url = 'https://pic.sogou.com/napi/pc/searchList'
count = 1 # 定义一个变量用于文件名字的指定
for i in range(0, 97, 48):
# print(i)
params = get_params(i)
response = requests.get(url=url, params=params)
json_data = response.json()
list_data = json_data['data']['items']
for data in list_data:
img_url = data['picUrl']
print(img_url)
try:
# 请求图片数据
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'}
img_data = requests.get(url=img_url, timeout=3, headers=headers).content
file_name = str(count) + '.png'
with open('img\\' + file_name, mode='wb') as f:
f.write(img_data)
count += 1 # 自增
except Exception as e:
print(e)
continue
print('*' * 50)
"""
- 课上肯德基案例, 将北京,上海,广州三个城市的门店信息获取下来
- 获取下来的信息用print函数打印即可
请在下方实现代码:
"""
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'}
def get_page(city_name):
"""
传入城市名, 计算当前成一共有多少页数据
:param city_name: 城市名
:return: 城市对应的数据页数
"""
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx'
params = {'op': 'keyword'} # 查询参数
data = { # 请求参数
'cname': '',
'pid': '',
'keyword': city_name,
'pageIndex': '1',
'pageSize': '10'
}
response = requests.post(url=url, params=params, data=data, headers=headers)
json_data = response.json()
count = json_data['Table'][0]['rowcount']
# print(count)
if count % 10 > 0: # 171取余10余1
page_num = count // 10 + 1
else:
page_num = count // 10
return page_num
# print(get_page('武汉'))
def send_request(keyword):
page = get_page(keyword)
for page in range(1, page + 1):
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx'
params = {'op': 'keyword'} # 查询参数
data = { # 请求参数
'cname': '',
'pid': '',
'keyword': keyword,
'pageIndex': str(page),
'pageSize': '10'
}
# data是构建post请求的请求参数关键字
response = requests.post(url=url, params=params, data=data, headers=headers)
json_data = response.json()
# print(json_data)
list_data = json_data['Table1']
for res in list_data:
storeName = res['storeName']
addressDetail = res['addressDetail']
pro = res['pro']
print(storeName, addressDetail, pro)
if __name__ == '__main__':
all_city = ['北京', '上海', '广州']
for city in all_city:
print(f'========================正在抓取 {city} 城市的数据======================')
send_request(city)
"""
目标网址: http://www.zfcg.sh.gov.cn
作业要求:
1. 点击页面导航栏中 "采购公告" 栏目
2. 采集下面公告信息数据, 需要采集以下数据:
title 公告标题
districtName 公告区域
3. 采集完后打印输出即可
请在下方完成代码:
"""
import requests
url = 'http://www.zfcg.sh.gov.cn/portal/category'
json_data = {"pageNo": 1, "pageSize": 15, "categoryCode": "ZcyAnnouncement1", "_t": 1687780627000}
# json 以json数据提交的请求参数
response = requests.post(url=url, json=json_data)
json_data = response.json()
print(json_data)
for data in json_data['result']['data']['data']:
title = data['title']
districtName = data['districtName']
print(title, districtName)