python爬虫方法和示例以及应对反爬

发布于:2025-08-13 ⋅ 阅读:(10) ⋅ 点赞:(0)

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)