爬虫小白学习日记(二)

学习目标:

  • 学习urlliib库基本操作

学习内容:

一、urllib库下载源码、图片、视频

爬取百度网页的源代码:
下面展示一些

# 导入所需要的库
import urllib.request

# 目标地址
url="http://www.baidu.com"

# 模拟浏览器向服务器发送请求
response=urllib.request.urlopen(url)

#获取源代码(注意要查看网页的编码格式,如下图解释)
content=response.read().decode("utf-8")

# 打印网页的源代码
print(content)

获取源代码的编码格式,用来解析源码
在这里插入图片描述

1. 爬取源码

# -------------------------------目标地址-------------------------------
url_page="http://www.baidu.com"

# -------------------------------模拟浏览器向服务器发送请求将数据下载到本地-------------------------------
urllib.request.urlretrieve(url_page,"baidu.html") #第一个参数表示抓取目标地址  第二个参数表示保存到本地“./baidu.html"文件中 【该段意思为保存百度源码到本地】
# urlretrieve()方法直接将远程数据下载到本地

2. 爬取图片

# --------------------------------下载图片------------------------------
url_img="https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/topnav/newxueshuicon-a5314d5c83.png"
urllib.request.urlretrieve(url_img,'xuesu.jpg')

3. 爬取视频
参考链接:https://blog.csdn.net/Angry_Mills/article/details/82705595
爬取视频目标网页为例子
在这里插入图片描述
src属性为 src=“blob:https://open.gaodun.com/b9d3366f-87ef-4328-9d97-31110de519a1”
但是复制打开该链接找不到视频内容 无法进行爬取

分析原因:
网页隐藏了真实的视频链接防止恶意爬取策略

解决方案:
找真实地址,利用抓包工具 打开XHR
XHR的定义

二、urllib定制请求头

对于编写爬虫过程中,有一些网站会有设置反爬机制:对于非浏览器的访问拒绝响应;或短时间频繁爬取会触发网站的反爬机制,导致 ip 被封无法爬取网页。这就需要在爬虫程序中修改请求的 headers 伪装浏览器访问,或者使用代理发起请求。从而绕开网站的反爬机制获取正确的页面。

#------------------------------利用urllib库模拟请求头信息--------------------------------------------
url="https://www.baidu.com"

# 定制我们的请求头信息 模拟成请求是由Chrome浏览器发出
headers={ 'user-agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'}

# 伪装请求头信息,制造符合服务器要求的请求信息
request=urllib.request.Request(url,headers=headers)

# 给服务器发送请求
response=urllib.request.urlopen(request)

# 将响应信息利用解码格式解码
content=response.read().decode()

print(content)
UA(User Agent) 用户代理,使服务器能够识别客户使用的操作系统以及版本、CPU、浏览器版本、浏览器内核、浏览器渲染引擎、浏览器语言插件等

三、urllib爬GET请求的数据操作

对于有一些网站的请求是用到GET的方式请求
在这里插入图片描述
此时如果采用传统的直接使用传统的方法来爬取会报错

# -----------------------------利用urllib库进行GET方式的爬虫-------------------------------------
# 目标地址
url="https://www.runoob.com/python3/python-urllib.html"

# 定制请求头信息
headers={
    'user-agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
}

# 制定请求信息
request=urllib.request.Request(url=url,headers=headers)

# 给服务器发送请求
response=urllib.request.urlopen(request)

# 解码响应内容
content=response.read().decode('UTF-8')

# 打印请求内容
print(content)

报错内容:
在这里插入图片描述
原因分析:
此时网站的编码确实是用utf-8
在这里插入图片描述
所以这个原因是网站为了反爬设置的陷阱,他是因为在请求响应中设置了压缩属性,所以让我们得到源码后不能解析出来,参考链接 Python爬取网页Utf-8解码错误及gzip压缩问题的解决办法
在这里插入图片描述
解决方案:
先对爬取得到的网站信息进行解压然后再进行解码
整体代码:

# -----------------------------利用urllib库进行GET方式的爬虫-------------------------------------
# 目标地址
url="https://www.runoob.com/python3/python-urllib.html"

# 定制请求头信息
headers={
    'user-agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
}

# 制定请求信息
request=urllib.request.Request(url=url,headers=headers)

# 给服务器发送请求
response=urllib.request.urlopen(request)

# 解码响应内容
# 获取响应内容
content=response.read()
# 解压并解码响应内容
content=gzip.decompress(content).decode('UTF-8')

# 打印请求内容
print(content)

采用urllib库中的parse对象的quote方法
对于url中有单个中文的编码的话 建议采用quote方法

# --------------------------利用urllib中的quote方法----------------------------------------
# 适用范围,比如目标地址中有编码的问题,比如中文等

# 目标地址 "https://www.baidu.com/s?wd=周杰伦"
url="https://www.baidu.com/s?wd="

# 定制请求头信息 需要 'Accept'因为如果不加上百度服务器会返回百度验证
headers={
    'user-agent' : 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_6 like Mac OS X) AppleWebKit/604.5.6 (KHTML, like Gecko) Mobile/15D100 QQ/7.5.0.407 V1_IPH_SQ_7.5.0_1_APP_A Pixel/750 Core/UIWebView Device/Apple(iPhone 7) NetType/WIFI QBWebViewType/1',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'
}

# 需要将url中需要编码的内容进行编码
name=urllib.parse.quote("周杰伦")
# 拼接url
url=url+name
print(url)

# 制定请求信息
request=urllib.request.Request(url=url,headers=headers)

# 给服务器发送请求
response=urllib.request.urlopen(request)

# 获取响应内容
content=response.read().decode("utf-8")

# 打印请求内容
print(content)

采用urllib库中的parse对象的urlencode方法
对于url中有多个参数编码的话 建议采用urlencode方法

# --------------------------利用urllib中的urlencode方法----------------------------------------
# 适用范围,比如目标地址中有多个参数编码的问题,比如中文等

# 目标地址 "https://www.baidu.com/s?wd=周杰伦&sex=男&location=中国台湾省"
base_url="https://www.baidu.com/s?"
# 将url后面的参数用unicode编码整合
data={
    "wd":"周杰伦",
    "sex":"男",
    "location":"中国台湾省"
}
data=urllib.parse.urlencode(data)
print(data)

url=base_url+data

# 定制请求头信息
headers={
    'user-agent' : 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_6 like Mac OS X) AppleWebKit/604.5.6 (KHTML, like Gecko) Mobile/15D100 QQ/7.5.0.407 V1_IPH_SQ_7.5.0_1_APP_A Pixel/750 Core/UIWebView Device/Apple(iPhone 7) NetType/WIFI QBWebViewType/1',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'
}

# 需要将url中需要编码的内容进行编码
name=urllib.parse.quote("周杰伦")
# 拼接url
url=url+name
print(url)

# 制定请求信息
request=urllib.request.Request(url=url,headers=headers)

# 给服务器发送请求
response=urllib.request.urlopen(request)

# 获取响应内容
content=response.read().decode("utf-8")

# 打印请求内容
print(content)

四、urllib爬Post请求的数据操作

post请求一般是有数据表单 而且再url中不会显示表单内容,因此请求信息中要编码制作成请求体中

使用案例:
通过以上所学知识,利用urlib库完成爬取翻译网页

注意事项:
要利用抓包工具抓出post请求表单中data数据的key
在这里插入图片描述

# -------------------------------------利用urllib库完成对于Post请求的爬取-------------------------------------
# 目标地址
url="https://fanyi.baidu.com/sug"

# 定制请求头
headers={
    'user-agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
}

# post请求的表单数据
base_data={
    "wk":"spider"
}
print(type(base_data)) #<class 'dict'>

# 还得用unicode统一编码
unicode_data=urllib.parse.urlencode(base_data)
print(type(unicode_data))#<class 'str'> 字符串的编码格式默认为utf-8
print("该变量的编码格式是:", unicode_data.encode())

# 还得字符串转成bytes类型
bytes_data=unicode_data.encode("utf-8")
print(type(bytes_data))#<class 'bytes'>

# post请求的数据不能拼接到url中而是要封装成请求体
# 定制请求信息 data的数据使byte类型
request=urllib.request.Request(url=url,data=bytes_data,headers=headers)

# 模拟浏览器向服务器发送请求
response=urllib.request.urlopen(request)

# 获取响应数据内容
content=response.read().decode("utf-8")

print(content)

问题
遇到问题就是会出现未知错误 errno:1000
在这里插入图片描述

五、爬取豆瓣电影首页的数据 GET请求案例

1、抓包工具找到抓取请求地址
在这里插入图片描述
在这里插入图片描述
整体代码:

# ------------------------------爬取豆瓣电影首页信息-------------------------------
# 寻找目标地址
base_url="https://movie.douban.com/j/chart/top_list?type=1&interval_id=100%3A90&action=&start=0&limit=20"

# 伪装UA请求头
headers={
    'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
}

# 定制请求信息
request=urllib.request.Request(url=base_url,headers=headers)

# 发送请求信息
response=urllib.request.urlopen(request)

# 解码获取响应数据
content=response.read().decode("utf-8")

# 将数据保存到本地 open方法默认的编码格式未GBK 因为内容中有中文所以要制定编码格式未unicode
fp=open('douban.json','w',encoding="utf-8")
fp.write(content)
fp.close()

print(type(content)) #<class 'str'>
print(content)

补充知识内容:
JSON字符串JSON对象以及普通字符串的区别
爬取豆瓣信息的内容为JSON数据中的数组结构
在这里插入图片描述

拓展练习一:爬取豆瓣前十页的电影信息

情景:AJAX的get请求
Ajax是什么?Ajax的作用和使用
如何判断网页是AJAX请求
通过判抓包工具中抓的请求头数据为XMLHttpRequest对象在这里插入图片描述

# _*_ coding : utf-8 _*_
# @Time : 2024/4/10 14:09
# @Author : HHL
# @File : 豆瓣前十页电影信息
# @Project : Python基础

# 分析:
# https://movie.douban.com/j/chart/top_list?type=1&interval_id=100%3A90&action=&start=0&limit=20
# https://movie.douban.com/j/chart/top_list?type=1&interval_id=100%3A90&action=&start=20&limit=20
# https://movie.douban.com/j/chart/top_list?type=1&interval_id=100%3A90&action=&start=40&limit=20
# 原理:
# page  1 2  3
# start 0 20 40
# start=(page-1)*20

import urllib.request
import urllib.parse


def get_request(page):
    # 确认目标地址
    base_url="https://movie.douban.com/j/chart/top_list?type=1&interval_id=100%3A90&action=&"
    headers={
        'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
    }
    data={
        "start":(page-1)*20,
        "limit":20
    }
    data=urllib.parse.urlencode(data)
    goal_url=base_url+data

    # 定制请求对象 该请求的方式为get所以不需要data参数
    request=urllib.request.Request(url=goal_url,headers=headers)
    return request

def get_response(request):
    response=urllib.request.urlopen(request)
    return response
def save_data(content,page):
    with open('douban'+str(page)+".json",'w',encoding="utf-8") as fp:
        fp.write(content)

if __name__ == '__main__':
    start_page=int(input("please enter start page:"))
    end_page = int(input("please enter end page:"))

#  串级爬取数据
    for page in range(start_page,end_page+1):
        # 定制请求对象
        request = get_request(page)
        # 向服务器发送请求
        response=get_response(request)
        # 获取响应内容
        content=response.read().decode("utf-8")
        # 保存到本地
        save_data(content,page)
        print("爬取第"+str(page)+"页数据成功")

在这里插入图片描述

拓展练习二:爬取肯德基官网信息

情景:AJAX的post请求
爬取佛山哪些位置有肯德基

为什么data数据需要两次编码
因为第一次(urlencode)是要将data数据unicode为以下第二张view source的格式
第二次编码是需要将datra数据变成二进制bytes类型,因为Request函数中的data必须是bytes类型
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

# _*_ coding : utf-8 _*_
# @Time : 2024/4/10 23:54
# @Author : HHL
# @File : 爬取肯德基佛山前十页地址信息
# @Project : Python基础

# 分析
# https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname 第一页
# cname: 佛山
# pid:
# pageIndex: 1
# pageSize: 10

# https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname 第二页
# cname: 佛山
# pid:
# pageIndex: 2
# pageSize: 10

# https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname 第三页
# cname: 佛山
# pid:
# pageIndex: 3
# pageSize: 10
import urllib.request
import urllib.parse


def get_request(page):
    #   目标地址
    base_url = "https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname"
    #   请求头伪装
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
    }
    #   请求体数据
    data = {
        'cname': '佛山',
        'pid': '',
        'pageIndex': page,
        'pageSize': '10'
    }
    # post请求中要为data数据编码两次
    encode_data = urllib.parse.urlencode(data)
    bytes_data = encode_data.encode("utf-8")  # 目的是转化为bytes类型给Request函数用
    # 请求对象定制
    request = urllib.request.Request(url=base_url, headers=headers, data=bytes_data)
    return request


def get_response(request):
    #     给服务器发送请求
    response = urllib.request.urlopen(request)
    return response


def get_content(response):
    content = response.read().decode("utf-8")
    return content


def save_data(content, page):
    with open("KFCLocation" + str(page) + ".json", "w", encoding='utf-8') as fp:
        fp.write(content)
    print("爬取肯德基第" + str(page) + "页数据成功")


if __name__ == '__main__':
    start_page = int(input("please enter start page:"))
    end_page = int(input("please enter end page:"))
    for page in range(start_page, end_page + 1):
        # 定制请求对象
        request = get_request(page)

        # 向服务器中发送请求得到响应数据
        response = get_response(request)

        # 获取响应内容
        content = get_content(response)

        # 将数据保存到本地中
        save_data(content, page)

  • 19
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值