Part-04/通过案例学爬虫(图片下载)
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
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