使用BeautifulSoup和Requests实现一个简单的图片爬虫

发布于 20 天前  86 次阅读


1.前言

最近的这段时间是真的难熬,每天在家坐着不能出去,甚至玩游戏都觉得无聊,自己又不爱看小说电影电视剧。总该干点有意思的事情吧?

考虑到开学后要申请转入计算机科学专业,不如自己先学点有意思的,入门一下Python吧。

我比较喜欢任务型学习,而不是过早的将最抽象最晦涩的定义熟悉个遍,就像第一次玩PUBG不是要记住各种武器参数而是直接进去突突突。

我一直对爬虫比较感兴趣,也想自己做一个,于是我首先尝试使用BeautifulSoup进行了一次爬虫实验。

我觉得爬虫里最简单的应该是图片爬虫,解析数据,拿到图片链接,下载保存就好了。

2.爬什么地方的图?

哪里有大量图片让我爬。。?我也不知道为什么就想到了

https://fulibus.net/

福利吧的福利汇总合集系列有大量的图片,并且网站使用的是WordPress,页面结构比较整齐。

内容不重要,主要是学习一下爬虫的运用

干正事,图片的内容都是次要的

多打开几个福利汇总的文章,观察一下链接,可以比较容易的得到规律

https://fulibus.net/2019090.html

2019福利汇总第90期

https://fulibus.net/2020001.html
2020福利汇总第1期

在这里,我通过Excel快速的生成了一个链接列表并检查了链接的HTTP状态,并将有效链接整理到url.txt,内容如下

https://fulibus.net/2020001.html
https://fulibus.net/2020002.html
https://fulibus.net/2020003.html
….
https://fulibus.net/2020015.html
https://fulibus.net/2019089.html
..
https://fulibus.net/2019178.html

不过,我要爬的图都在福利集合的第二页,所以url.txt的内容需要稍做处理

https://fulibus.net/2020001.html/2
https://fulibus.net/2020002.html/2
https://fulibus.net/2020003.html/2
….
https://fulibus.net/2020015.html/2
https://fulibus.net/2019089.html/2
..
https://fulibus.net/2019178.html/2

3.前置工作

首先,得知道图片都在哪个位置

我在这里拿 https://fulibus.net/2020004.html/2 做个例子

使用Chrome Dev Tools 的 Elements 选项卡来观察一下页面结构

可以看到,文章里的每个图片都在一个单独的 <img> 标签里,而这些标签属于若干个<p>标签,最后,这些<p>标签属于一个类别(class)名为article-content的<article>标签,很明显,这个标签就是文章的主体。

接下来是 Request Headers头的模拟,对于福利吧,只需要UA就够了,

我在 WhatsMyUA.info 获取到了自己的UA

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36

4.写代码

首先,起个名字 PicDownMultiUrls.py

把要用到的Moudles引用一下,顺便先把headers写好。

from bs4 import BeautifulSoup
import requests
import os #文件操作
headers = {'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36"}

整个程序的思路大概是这样

百度脑图好难用

为了简化程序,所有的文件读写操作都在同一个目录进行。

从脑图里分析一下,整个程序应该是两个循环嵌套在一起组成的,这里我用两个for循环实现了整个流程。

先把第一个循环写出来

for line in open('url.txt'):
url= line #逐行循环读取url.txt
print(url) #在Console返回当前正在解析下载的url
request = requests.get(url, headers=headers) #通过request.get获得页面
source = request.text #获得页面的文本形式源码
print(request) #返回HTTP状态码
page_soup = BeautifulSoup(source, 'html.parser')
#使用BeautifulSoup并调用内置html.parser解析器对html页面源码进行解析
imgs = page_soup.find('article', {'class': 'article-content'}).find_all('img')
# 寻找类别名为article-content的article标签,并寻找里面所有的img标签,放在imgs列表里

扔到Jupyer Notebook跑一下看看

输出结果

这里我顺便把 imgs 打印了一下,可以看到对于每次循环都会有3次输出

1.当前循环中的URL

2.爬虫访问URL返回的HTTP状态码

3.使用BeautifulSoup解析到的所有<img>标签的集合

这样子,我就可以拿到所有的包含图片链接的<img>标签了。

再写下一个循环

for each in imgs:    #循环依次选定imgs列表中的每一个img标签
imgurl = each['src'] #循环提取img标签中的src值并赋给imgurl
imgsource = requests.get(imgurl, headers=headers).content #通过requests.get的方法获得图片的二进制内容
filename = os.path.basename(imgurl) #定义一个变量,储存文件的原名
f = open(filename, 'wb') #新建一个名字为filename的文件,通过二进制方式写入
f.write(imgsource) #将imgsource写入文件中
f.close() #关闭文件,解除占用

把程序块拼起来,跑一下试试

好起来了

由于福利吧直接把图扔到微博图床再贴到文章里,所以文件名都比较不规则。

如果你想的话,可以采用 数字+扩展名 的方式进行保存,方法在源码中有写。

看上去整齐一些

本文章涉及到的文件:

 
https://bakaft.me/uploadings/Python/FulibaScrape/PicdownMultiUrls.py
PS:因为编码问题,直接打开里面的中文注释会乱码,建议下载后使用PyCharm等IDE查看

https://bakaft.me/uploadings/Python/FulibaScrape/url.txt

谢谢观看~