Part-04/通过案例学爬虫(图片下载)

本文介绍了如何使用Python的requests和pyquery库进行网络请求和数据解析,进而实现图片的下载。首先讲解了requests库的安装和使用,然后介绍了pyquery的安装和应用,接着详细阐述了发送网络请求、解析图片URL以及数据存储的步骤。最后,强调了版权信息和创作日期。
摘要由CSDN通过智能技术生成

1.导入第三方库

import requests
from pyquery import PyQuery as pq  # 从pyquery中导入PyQuery模块并将它重命名为pq

01.requests

001.requests的安装

	requests不是python内置的库,是第三方库,所以在使用之前需要手动安装(当然python内置的库就需要我们自己安装了),安装方法这里提供两个路径
	# 通道 1.通过电脑命令窗口:win+R打开-->输入cmd确定-->在弹出的黑窗口中输入一下命令![当出现这样的图片表示安装成功了] 见下图
	pip install requests 
	# 通道 2.通过pycharm的terminal安装,输入同样的代码,可以实现安装![当出现这样的时候就表示成功了] 见下图
	pip install requests

对应通道 1
对应通道 2

002.requests的使用

	首先在使用模块前切记要进行导入(无论是python内置的库还是第三方库)
	import  requests
	下面将为你展示requests的基本用法:(也不需要刻意去记,爬虫会经常用到慢慢就熟悉了)
	// 拿百度的网址来说:http://www.baidu.com
	#导入requests库
	import requests
	url = 'https://www.baidu.com'
	#发送一个get请求并得到响应
	resp = requests.get(url )
	#查看响应对象的类型
	print(type(resp ))
	#查看响应状态码
	print(resp .status_code)
	#查看响应内容的类型
	print(type(resp .text))
	#查看响应的内容
	print(resp .text)
	# 二进制数据 一般用于下载图片或者视频
	resp.content()
	#查看cookies
	print(resp .cookies)
	为了便于小伙伴们查看,给大家补充了这样一个表。
方法注释
resp = requests.get(url )发送一个get请求并得到响应(resp自定义命名)
type(resp )查看响应对象的类型
resp .status_code查看响应状态码
type(resp .text)查看响应内容的类型
resp .text查看响应的内容
resp .cookies查看cookies
resp.content()二进制数据(一般用于下载图片或者视频)

02.pyquery

001.pyquery的安装

	所有第三方库的安装和requests的安装一样,当个别第三方库的安装出现问题了再查阅资料去解决
	pip install pyquery

002.pyquery的使用

		首先在使用模块前切记要进行导入(无论是python内置的库还是第三方库)
	from pyquery import PyQuery as pq  # 从pyquery中导入PyQuery模块并将它重命名为pq
	下面将为你展示pyquery的基本用法,pyquery也是一个非常好用的提取工具:(也不需要刻意去记,爬虫会经常用到慢慢就熟悉了)
在介绍pyquery的基本使用之前,我们需要引出一个html来辅助我们,html不需要专门去看,到时候看网页源代码就很清楚了。大家对这个html应该是非常熟悉了
html_str='''<!DOCTYPE html>
<html>
<div><!--我是一个html文件,这些基本上是html常见的格式和标签--></div>
<head>
	<title class="aaa" id="t">pyquery的使用</title>
</head>
<body>
	<p>
		<ul>11111111</ul>
		<a class="a标签" id="就是a标签" href="wwww.baidu.com" >22222222</a>
	</p>
	<p>
		<u>33333333</u>
		<u>44444444</u>
		<div class="aaa" id="d3">55555555</div>
	</p>
	<div class="bbb" id="d1">66666666</div>
	<div class="ccc" id="d2">77777777</div>
</body>
</html>'''
	好了,现在我们的html也有了,开始进入pyquery的基本用法的学习吧!
# 首先导入我们的pyquery第三方库,可千万别忘了,到时候代码下面给你划红色波浪线就是在提醒你导入库
from pyquery import PyQuery as pq  # 从pyquery中导入PyQuery模块并将它重命名为pq
query = pq(html_str)   # 将html_str载入到pyquery,然后自定义变量名为query,后面直接使用query即可,和Beautifulsoup的soup的初始化、xpath的tree的初始化类似
   
# 第一步:我们把html_str打印出来看一下
print(query)   # 是整个html_str(如下)
"""<html>
<div><!--我是一个html文件,这些基本上是html常见的格式和标签--></div>
<head>
	<title class="aaa" id="t">pyquery的使用</title>
</head>
<body>
	<p>
		<ul>11111111</ul>
		<a href="wwww.baidu.com">22222222</a>
	</p>
	<p>
		<u>33333333</u>
		<u>44444444</u>
		<div class="aaa" id="d3">55555555</div>
	</p>
	<div class="bbb" id="d1">66666666</div>
	<div class="ccc" id="d2">77777777</div>
</body>
</html>"""
# 查看他的类型  为pyquery.pyquery.PyQuery  也就是我们用的py对象
print(type(query)) # <class'pyquery.pyquery.PyQuery'>

#
# 第二步,从PyQuery对象中提取内容
# 1. 标签选择器
title = query("title")
print(title) # title标签   <title class="aaa" id="t">pyquery的使用</title>

# 2. id选择器
a = query("#t")  # "#"是id选择的标识,表示选择id=“t”的整个标签
print(a)   # <title class="aaa" id="t">pyquery的使用</title>

# 3. 类选择器
b = query(".aaa")  # "."是类(class)选择的标识,表示选择class=“aaa”的整个标签(这里有两个)
print(b) # <title class="aaa" id="t">pyquery的使用</title> <div class="aaa" id="d3">55555555</div>
# NOTE:  通过pyquery选择器提取的节点,仍然是pyquery对象.就和我们之前下path的一样,先从html中提取出一个
#  一个div_list,然后遍历从每一个div从去提取内瓤,这个pyquery也是一样,称为链式提取
# 4. 链式提取
title = query("head")("title") # 先提取head, 然后再提取head里面的title.
print(title)
# 当然我们这样写会更为方便些(如下)
# 5. 后代选择器
title = query("head title") # 先提取head, 然后再提取head里面的title.
print(title)

# 6. 属性提取
a = query("body p a")    # 先提取到body标签,然后提取其中的p标签,然后提取其中的a标签
href = a.attr("href")    # 然后通过attr获取到a标签的href属性值
print(href)  # wwww.baidu.com

cla = a.attr("class")    # 然后通过attr获取到a标签的class属性值
print(cla)    # a标签

i = a.attr("id")         # 然后通过attr获取到a标签的id属性值
print(i)  # 就是a标签

# 7.内容提取  需要先定位到标签,然后用"标签.text()"的形式来获取
htm = a.html()
print(htm)  # 22222222
tex = a.text()
print(tex)  # 22222222

方法内容示例注释
通过标签名查找<标签名>query(“标签名”)title = query(“title”)直接在html_str中查询title标签,返回title标签
通过类名查找(class = “类名”)query(‘.类名’)query(“.aaa”)“.” 表示了类查找 表示选择class=“aaa”的整个标签
通过id名查找(id = “id名”)query(‘#id名’)query(“#t”)"#"是id选择的标识,表示选择id=“t”的整个标签
链式提取query(“上级标签”)(“下级标签”)query(“head”)(“title”)先提取head, 然后再提取head里面的title
后代选择器query(“上级标签 下级标签”)query(“head title”)先提取head, 然后再提取head里面的title
属性提取query(“上级标签…下级标签”).attr(“属性名”)query(“body p a”).attr(“href”)先提取到body标签,然后提取其中的p标签,然后提取其中的a标签,然后通过attr获取到a标签的href属性值
内容提取query(“上级标签…下级标签”).text()query(“body p a”).text()先定位到标签,然后用"标签.text()"的形式来获取
内容提取query(“上级标签…下级标签”).html()query(“body p a”).html()先定位到标签,然后用"标签.html()"的形式来获取

2.发送网络请求

	利用requests发送请求有两种方式get和post,这里我们做简要介绍,当需要发送post请求时会再次介绍。
	1.get
		def get(url, params=None, **kwargs):
		参数放在URL后面:http://httpbin.org/get?key1=value1&key2=value2
		参数使用params关键字接收,会自动拼接到url地址后面
		?:表示携带的参数,多个参数使用&分开
	2.post
		def post(url, data=None, json=None, **kwargs):
		url:请求地址
		data:请求参数 默认编码格式:form表单
		json:请求参数 默认编码格式:json 如果设置请求头为form表单,那么使用设置的方式。
	3.确定需要发送请求的方式:
		01.一般默认使用get发送请求,如果返回没有数据则不是
		02.具体使用get还是post见下图

在这里插入图片描述

import requests
def getHTMLText(url):   # 发送请求获取网页源码
    try:  #尝试,成功就运行,不成功就走except
        response = requests.get(url, headers=headers,timeout=30)  # 发送请求
        response.raise_for_status()
        response.encoding = 'utf-8' # 网页源代码的编码形式是“utf-8”
        # print(response.text)  # 打印页面源代码来查看是否请求成功
        return response   # 不返回页面源代码的原因是为了之后存储图片做准备(见下)
        # 页面源代码:  response.text
        # 图片是二进制: response.content
        # 这里写成response就是为了到时候返回response.content
    # except:  # try走不通就返回""
    #     return ""
    except Exception as e:  # try走不通就返回""
        print(e)  # 打印报错信息
        return ""  # 什么都不返回  None
url = 'https://www.nipic.com/photo/shengwu/jiaqin/index.html'  # 需要爬取的网址 # 昵图网--摄影--生物世界(熟悉了套路自己选即可)
html = getHTMLText(url) #这里是将发送请求封装成了一个函数:getHTMLText()

3.解析数据

	今天我们用的解析工具就是上面多次提到的pyquery
	step1.分析页面

这里标签比较清晰舒爽,使用我们之前学的Beautifulsoup和xpath来解析数据都没有任何问题,这里我们选择使用pyquery

在这里插入图片描述

	从上面可以出,我们的想要的数据都存储在<ul>标签下的<li>标签中,而每一个<li>标签代表一张图片信息
	step2.分析完页面,代码实现解析数据(分析页面和代码其实是同步进行的)
备注:(先看代码,这里备注的是ul标签的路径是如何快速获得的,也不能盲目使用,提示每写一步要做检查和调试)

在这里插入图片描述

import requests
from pyquery import PyQuery as pq
def parse(html):
    query = pq(html)   # # 将html_str载入到pyquery,然后自定义变量名为query,后面直接使用query即可,和Beautifulsoup的soup的初始化、xpath的tree的初始化类似
    li_list = query("body > div.new-layout-width.mbt-area.clearfix.layout-width > div > div.new-search-result.overflow-hidden > ul > li")
    # 这个偷懒做法见备注
    # li_list = query(".new-search-result-box clearfix li ")  # 先通过类选择找到ul标签,然后下一级选择li标签
    # print(li_list)
    for li in li_list.items():  # 遍历的时候注意要使用items()
        # print(li)
        print(li("a").attr("href"))  # 先得到li标签下的a标签然后在通过属性拿到href值
在这里我们可以看到出现了javascript这样不是我们想要的数据,同时href不是一个完整的url,还需要我们做一些拼接才可以拿来用接下来来看一看这两个小问题

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

我们返回到网页中去,发现其实javascript应该是对应的广告,我们可以通过简单的代码来过滤掉它(利用href=“javascript”),同时后面大家也可以看到有一个“下一页”的内容(利用href=“javascript:;”)
if (li("a").attr("href")=="javascript" or li("a").attr("href")=="javascript:;" ):   # 如果class!="relative block works-detail hover-none new-works-img-box"直接进入下一个循环,不执行下面的代码
	continue   # 通过跳过本循环实现过滤作用

在这里插入图片描述

通过urllib的urljoin做拼接
from urllib.parse import urljoin
if (li("a").attr("href")=="javascript" or li("a").attr("href")=="javascript:;" ):   # 如果href=="javascript"或者href=="javascript:;"直接进入下一个循环,不执行下面的代码
	continue   # 通过跳过本循环实现过滤作用
href = li("a").attr("href")  # 先得到li标签下的a标签然后在通过属性拿到href值
href = urljoin(url,href)  # 拼接url

在这里插入图片描述

拿到href之后,我们可以通过href进入图片的详情页面去提取图片的url,然后下载
# 发送请求   从href请求到的页面源代码中去提取图片的url
href_html = getHTMLText(href).text
query2 = pq(href_html)
img_src = query2(".works-img" ).attr("src")
print(title,img_src)

在这里插入图片描述

但是这里我们也需要做url拼接,把上面的代码copy下来,然后简单将href修改为img_src

在这里插入图片描述
得到了图片的下载地址img_src了之后,我们可以开始数据存储了!

4.数据存储

像图片类型的数据,我们一般直接做数据存储,像这种简单的数据存储,我们可以在得到img_src值之后就进行存储了

在这里插入图片描述

	print(f"{title}图片正在抓取中...")
        with open(f"./生物世界/{title}.png",mode="wb") as f:  # 注意这里的mode=“wb”写入的是二进制文件(图片)
            response =  requests.get(img_src)
            f.write(response.content)   # 注意这里是response.content
        print(f"{title}图片抓取完毕,已保存至生物世界/{title}.jpg中")
    print("所有图片已抓取完成....")
最后我们可以为代码加入一些运行提示信息(我已加入代码中相信你已经看见了)
# parse()函数完整代码:
def parse(html):
    query = pq(html)   # # 将html_str载入到pyquery,然后自定义变量名为query,后面直接使用query即可,和Beautifulsoup的soup的初始化、xpath的tree的初始化类似
    li_list = query("body > div.new-layout-width.mbt-area.clearfix.layout-width > div > div.new-search-result.overflow-hidden > ul > li")
    # 这个偷懒做法见备注
    # li_list = query(".new-search-result-box clearfix li ")  # 先通过类选择找到ul标签,然后下一级选择li标签
    # print(li_list)
    for li in li_list.items():  # 遍历的时候注意要使用items()
        # print(li)
        # print(li("a").attr("href"))  # 先得到li标签下的a标签然后在通过属性拿到href值
        if (li("a").attr("href")=="javascript" or li("a").attr("href")=="javascript:;" ):   # 如果href=="javascript"或者href=="javascript:;"直接进入下一个循环,不执行下面的代码
            continue   # 通过跳过本循环实现过滤作用
        href = li("a").attr("href")  # 先得到li标签下的a标签然后在通过属性拿到href值
        # print(href)
        # url拼接  导入urllib模块   from urllib.parse import urljoin
        href = urljoin(url,href)
        # print(href)
        # 数据存储    因为现在得到的是一个url,还是需要先发送请求,但是我们发送请求的模块被我写死了(只能返回response.text,而我们需要的是response.content,所以我们在这里直接写发送请求的部分)
        # 获取title作为文件名
        title = li("a").attr("title")
        # 发送请求   从href请求到的页面源代码中去提取图片的url
        href_html = getHTMLText(href).text
        query2 = pq(href_html)
        img_src = query2(".works-img" ).attr("src")
        img_src = urljoin(url,img_src)
        # print(title,img_src)
        print(f"{title}图片正在抓取中...")
        with open(f"./生物世界/{title}.png",mode="wb") as f:  # 注意这里的mode=“wb”写入的是二进制文件(图片)
            response =  requests.get(img_src)
            f.write(response.content)
        print(f"{title}图片抓取完毕,已保存至生物世界/{title}.jpg中")
    print("所有图片已抓取完成....")
最后检查一下是否有问题

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

	结语:本人不是计算机专业,也是通过业余时间对爬虫进行学习 ,会慢慢把自己的学习汇总为框架和遇到的问题整理出来,一是为了自己复习巩固的时
	候,再次可以通过自己的文章来解答疑惑,二是想通过编辑文章的方式来促进自己的学习,三是如果有小伙伴需要也可以用来借鉴,有任何不足之处,
	恳请大家批评指正,谢谢!
	此博客为个人博客,不涉及商业用途,仅提供学习参考,内容均来自个人原创以及互联网转载和摘录。
	此博客上带有原创标识的文章.图片.文件等,未经本人允许,不得用于商业用途以及传统媒体。网络媒体或个人转载请注明出处和链接,否则属于侵权行为。

版权声明:

@就叫李二狗原创作品,转载必须标注原文链接

Copyright 2023

Crated:2023-01-15

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值