python爬虫方法和示例以及应对反爬
基础形式
#使用urllib来获取百度首页的源码
import urllib.request
#定义一个url 就是你要访问的地址
url = 'http://www.baidu.com'
#模拟浏览器向服务器发送请求 获取响应内容
response = urllib.request.urlopen(url)
#获取响应中的页面的源码 获取页面源码内容
#read方法 返回的是字节形式的二进制数据
#将二进制数据转换为字符串
#二进制=>字符串 (解码) decode('编码的格式')
content = response.read().decode('utf-8')
print(content)#打印出页面源码的字符串形式
一个类型六个方法
import urllib.request
url = 'http://www.baidu.com'
#模拟浏览器向服务器发送请求
response = urllib.request.urlopen(url)
#一个类型和六个方法
# print(type(response)) #<class 'http.client.HTTPResponse'> 类型
# #按照字节去读,效率较慢
# content = response.read(5) #逐字节读取页面源码的二进制形式
# print(content) #read中的参数指定读取多少个字节 b'<!D
#读取一行
# content = response.readline()
# print(content) #b'<!DOCTYPE html>\n'
#读取全部行
# content = response.readlines()
# print(content)
#返回状态码 200代表正常
# print(response.getcode()) #200
#返回url地址
# print(response.geturl()) #http://www.baidu.com
#获取的一些状态信息
# print(response.getheaders())#('Accept-Ranges', 'bytes')....
爬取网页/图片/视频
对于不同格式的文件要注意好后缀,以及目标url是可以直接有效访问的
import urllib.request
#下载网页
url_page = 'http://www.baidu.com' #在python中,可以写变量的名字也可以写值
response = urllib.request.urlretrieve(url_page,'baidu.html')
#下载图片
url_img = 'https://ts1.tc.mm.bing.net/th/id/R-C.ddb5c489295b78eaf4b165a5283e16a6?rik=aHbfoE9vIMWF0Q&riu=http%3a%2f%2fn.sinaimg.cn%2fsinacn10116%2f547%2fw1166h981%2f20181217%2f63c9-hqhtqsp4655905.jpg&ehk=LrHdlydavJv8PPcixAi4uE1gHCkdfaGVIDc9zAacEYI%3d&risl=&pid=ImgRaw&r=0'
urllib.request.urlretrieve(url_img,'beartwo.jpg')
#下载视频
url_viedo = 'http://vodpub6.v.news.cn/yqfbzx-original/20230818/20230818bd5de7446029436cb41e0ff2c37e1c54_606f38a617a746988c4bb396538066dd.mp4'
urllib.request.urlretrieve(url_viedo,'xiongchumo.mp4')
应对基础反爬
定制请求对象,可以应对基础的反爬
import urllib.request
url = 'https://www.baidu.com'
#url的组成
# http / https www.baidu.com 80/443
# 协议 主机 端口号 路径 参数 锚点
# response = urllib.request.urlopen(url)
#
# content = response.read().decode('utf-8')
#
# print(content) #此时得到的数据收到限制不完整,遇到了反爬
#在需要爬取的指定网页的network的响应头中找到User_Agent
#user-agent
#Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0
#构造成字典形式
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0'
}
#请求对象的定制 因为urlopen方法中国不能存储字典,所以无法使用headers
#错误用法 : response = urllib.request.urlopen(url,headers)
#正确定制
#因为参数顺序的问题,不能够直接写url和headers,中间还有data,所以需要关键字穿参
request = urllib.request.Request(url=url,headers=headers)
#定制包装好后,再使用urlopen打开
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content) #获取到完整内容
quote方法转码 (unicode编码是统一使用的编码)
#将'熊二'变成unicode编码的格式
#需要依赖于urllib.parse
name = urllib.parse.quote('熊二')
print(name) #%E7%86%8A%E4%BA%8C
多个数据的合并转码
import urllib.parse
data = {
'wd':'周杰伦',
'sex':'男',
'location':'中国台湾省'
}
a = urllib.parse.urlencode(data)
print(a)
# wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7&location=%E4%B8%AD%E5%9B%BD%E5%8F%B0%E6%B9%BE%E7%9C%81
多数据合并转码请求
如果没有被爬的话,能获取,不然就爬不到(废话文学)
import urllib.parse
import urllib.request
import urllib.parse
base_url = 'https://www.baidu.com/s?'
data = {
'wd':'周杰伦',
'sex':'男',
'location':'中国台湾省'
}
new_data = urllib.parse.urlencode(data)
url = base_url + new_data
#请求资源路径
print(url)
#cookie
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0',
}
#请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
#模拟浏览器向服务器发请求
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)
post请求爬取百度翻译
可以使用爬虫利用百度翻译开放的sug端口,进行自动识别的英语单词和中文词语之间的翻译
例如 thorough -> 彻底的,全面的 天气 -> weather
import urllib.request
import urllib.parse
url = 'https://fanyi.baidu.com/sug'
headers = {#包含了关键的 User-Agent,模拟浏览器请求,避免被简单识别为爬虫
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0',
}
#注释中的 Cookie 虽然未启用,但该接口对 Cookie 依赖较低(测试时即使不带 Cookie 也能返回结果),
# 这也是代码能正常运行的原因之一。如果后续接口限制严格,可取消注释启用 Cookie。
#定义需要翻译的数据
text = input('请输入需要翻译的单词:')
data = {
'kw':text
}
#post请求的参数必须要进行编码 #并且编码之后必需调用encode方法
data = urllib.parse.urlencode(data).encode('utf-8')
#正确使用 urllib.parse.urlencode(data) 对字典参数进行 URL 编码,
# 再用 encode('utf-8') 转为字节流,符合 POST 请求对参数格式的要求(POST 数据需为字节类型)。
#定制请求对象
request = urllib.request.Request(url=url,data=data,headers=headers)
#模拟浏览器发请求
response = urllib.request.urlopen(request)
#获取响应的数据
content = response.read().decode('utf-8')
print(content)#str 现在是个JSON对象的字符串形式
#{"errno":0,"data":[{"k":"spider","v":"n. \u8718\u86db;
#使用 json.loads() 转为 Python 字典
import json
obj = json.loads(content)
print(obj)
#得到具体的数据
#{'errno': 0, 'data': [{'k': 'spider', 'v': 'n. 蜘蛛; 星形轮,十字叉; 带柄三脚平底锅;
print(text+'翻译的结果:'+obj['data'][0]['v']) #筛选出第一条数据
#也可以使用print(obj.get('data')[0].get('k'))
#使用 get 方法获取 data 列表(若 data 不存在,默认返回 None,避免直接用 obj['data'] 可能出现的 KeyError)
Ajax的GET爬取豆瓣电影
首先是爬取第一页的整个数据
import urllib.request
#GET请求
#获取豆瓣电影的第一页的数据并且保存起来
url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0',
}
#请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
#获取响应的数据
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
#[{"rating":["9.4","50"],"rank":1,"cover_url":"https://img9.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p2913554676.jpg"
#数据下载到本地
#open方法默认情况下是gbk编码,如果想要保存汉字,那么需要指定encoding='utf-8'
# fp = open('douban.json','w',encoding='utf-8')
# fp.write(content)
# fp.close()
#上面的fp文件下载步骤可以用下列代码代替
with open('douban.json','w',encoding='utf-8') as fp:
fp.write(content)
douban.json
的文件内容
[{"rating":["9.4","50"],"rank":1,"cover_url":"https://img9.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p2913554676.jpg","is_playable":true,"id":"1295644","types":["剧情","动作","犯罪"],"regions":["法国","美国"],"title":"这个杀手不太冷","url":"https:\/\/movie.douban.com\/subject\/1295644\/","release_date":"2024-11-01","actor_count":23,"vote_count":2499435,"score":"9.4","actors":["让·雷诺","娜塔莉·波特曼","加里·奥德曼","丹尼·爱罗","彼得·阿佩尔","迈克尔·巴达鲁科","艾伦·格里尼","伊丽莎白·瑞根","卡尔·马图斯维奇","弗兰克·赛格"],"is_watched":false},{"rating":
《..................................................................................
.................................中间省略一大部分.....................................
....................................................................................》
["8.8","45"],"rank":20,"cover_url":"https://img9.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p1596085504.jpg","is_playable":true,"id":"1298070","types":["动作","冒险","奇幻"],"regions":["美国"],"title":"加勒比海盗","url":"https:\/\/movie.douban.com\/subject\/1298070\/","release_date":"2003-11-21","actor_count":35,"vote_count":946119,"score":"8.8","actors":["约翰尼·德普","杰弗里·拉什","奥兰多·布鲁姆","凯拉·奈特莉","杰克·达文波特","乔纳森·普雷斯","贾尔斯·纽","陆建艺","大卫·拜利","王磊"],"is_watched":false}]
爬取指定页到指定页的数据
import urllib.request
import urllib.parse
#https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
#start=0&limit=20
#https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
#start=20&limit=20
#https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
#start=40&limit=20
#https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
#start=60&limit=20
#通过查看每页的url地址可以找到规律在start上
#start ( page - 1 ) * 20 第page页
#下载豆瓣电影前十页的数据
#定义函数
def create_request(page):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0',
}
#url地址的配置
base_url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&'
data = {
'start': (page - 1) * 20,
'limit': 20,
}
data = urllib.parse.urlencode(data)
url = base_url + data
#请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
return request
def get_content(request):
# 获取响应数据
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
def down_load(page,content):
#下载数据
with open('douban' + str(page) + '.json', 'w', encoding='utf-8') as fp:
fp.write(content)
#程序的入口 main函数
if __name__ == '__main__':
start_page = int(input('请输入起始的页码'))
end_page = int(input('请输入结束的页码'))
for page in range(start_page, end_page+1):
# 每一页都有自己的请求对象定制
# request = create_request(page)
# 获取响应数据
# content = get_content(request)
# 下载数据
# down_load(page,content)
# 当然,上述三个步骤可以合成一个
down_load(page,get_content(create_request(page)))
Ajax的POST爬取肯德基官网
#以此分析每页的数据
#第一页
#https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# POST
#from data 数据
# cname:北京
# pid:
# pageIndex:1
# pageSize:10
#第二页
# https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# POST
#from data 数据
# cname:北京
# pid:
# pageIndex:2
# pageSize:10
#发现 规律都在于 pageIndex 属性
import urllib.request
import urllib.parse
#post请求的数据必需编码,引入parse
from 爬虫学习.GET豆瓣电影的前十页 import create_request
def create_request(page):
base_url = 'https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
data = {
'cname': '北京',
'pid':'',
'pageIndex':page,
'pageSize':10
}
# post请求的数据必需编码,引入parse
data = urllib.parse.urlencode(data).encode('utf-8')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0',
}
#定制请求对象
request = urllib.request.Request(url = base_url, data=data, headers=headers)
return request
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
def down_load(page,content):
with open('kfc'+str(page)+'.json', 'w', encoding='utf-8') as fp:
fp.write(content)
if __name__ == '__main__' :
start_page = int(input('请输入起始页码'))
end_page = int(input('请输入结束页码'))
for page in range(start_page, end_page+1):
#请求对象的定制
request = create_request(page)
#获取网页源码
content = get_content(request)
#下载数据
down_load(page,content)
异常监听
使用语法
import urllib.error
#当try部分的代码运行时遇到错误,可以被except的两种错误组件监听
try
print('被监听的部分')
....
....
except urllib.error.HTTPError:
print('HTTPError错误发生.....')
#可以运行指定的逻辑.....
except urllib.error.URLError:
print('URLError错误发生......')
#可以运行指定的逻辑.....
微博的Cookie登录
#使用的场景:数据采集的时候 需要绕过登录,然后进入到某个页面
#个人信息页面是utf-8 但是还是报错了编码错误,因为并没有进入到个人信息页面 而是跳转到了登录页面
#那么登录页面不是utf-8所以报错
#什么情况下访问不成功
#因为请求头信息不够,所以不成功
#https://weibo.com/u/7921420233
import urllib.request
url = 'https://weibo.com/u/7921420233'
#在network中找到这些请求头
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-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'cache-control': 'max-age=0',
'cookie': 'XSRF-TOKEN=ej9CxERfI2EBT2uwV0MozNHe; SCF=Akr898maawAJgZkFCw2nUpb0ZiZXezanjfXLy26_5pHXq8AAUvO1WWrkNXGxKMdyqWss-kdyg9hWr-zBAv0hafo.; SUBP=0033WrSXqPxfM72wWs9jqgMF55529P9D9W5KBZPF9DJXUElj7xVl0Voo5JpVF020S0npSh2pSK-N; SUB=_2AkMfxMi4dcPxrARYmvkRzmvgb45H-jysEaFOAn7uJhMyAxh87kcRqSVutBF-XK6Gz3mQY4_elTpQBLIwavw6JG8E; WBPSESS=Dt2hbAUaXfkVprjyrAZT_Ia4cG4dTvjk1xxB1wSdnFhIZ3RB6i3_elVydlb_nlaxZemrFpNZGV_mmQai6Fm30fJlt4ea-31nzRx6NfosE3EgcQMog7MoUQ2OvTftuhp9NI5Gmzo0mndmpHs_ukTLig==',
'priority': 'u=0, i',
#referer判断的是不是由上一个路径进来的 一般情况下是做图片的防盗链
'referer': 'https://weibo.com/newlogin?tabtype=weibo&gid=102803&openLoginLayer=0&url=',
'sec-ch-ua': '"Not;A=Brand";v="99", "Microsoft Edge";v="139", "Chromium";v="139"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'same-origin',
'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/139.0.0.0 Safari/537.36 Edg/139.0.0.0'
}
#请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8') #需要在该处修改为gb2312
#然后发现得到的页面是登录页面
#将数据保存到本地
with open('weibo.html','w',encoding='utf-8') as fp:
fp.write(content)
现在反爬太严格了,所以要么是进不去,要么是强制到登录页,应该是动态cookie的问题。
此时我们需要更高级的请求头,请求对象的定制已经满足不了我们的需求(不能使用动态cookie和代理)
所以我们需要Handler处理器
Handler处理器
基本使用
# 需求 使用handler来访问百度 获取网页源码
import urllib.request
url = 'http://www.baidu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0',
}
request = urllib.request.Request(url=url, headers=headers)
#handler build_opener open
#获取handler对象
handler = urllib.request.HTTPHandler()
#通过handler获取opener对象
opener = urllib.request.build_opener(handler)
#调用open方法
response = opener.open(request)
content = response.read().decode('utf-8')
print(content)