1. 首页
  2. Python

(1)小小白Python爬虫入门教程之图片篇

作为一个小小白,写一个小小小白能看得懂的教程!

这篇教程的终极目的是尽量做到让小小白看完了可以直接动手爬图片。

建议一边打开软件写代码,一边看文章,出了问题在文中找答案。干看文章不动手是没有任何效果的

1,准备工作

1.这个教程是基于Python3.6来的,我使用的是Anaconda3里的Spyder,如下图

(1)小小白Python爬虫入门教程之图片篇
(1)小小白Python爬虫入门教程之图片篇

个人感觉还可以。

下载地址这里anaconda.com/download/

pan.baidu.com/s/1kV7nl5

2.然后是chrome浏览器,它右键菜单下有个检查,其实就是F12,可以在相应的位置查看网页的定义,非常方便。

3.在开始之前,可以先看一下这个博客: 小白爬虫第一弹之抓取妹子图 | 静觅

这篇文章给了我很大帮助,致敬哎哟卧槽!

2,开始上手

作为例子,这次准备爬网站zhuoku.com/ 的图片。

别问我为啥不爬妹子图,网上爬妹子图的教程实在太多了!

当然,好好看懂这篇教程之后,爬妹子图就完全不在话下了

(1)小小白Python爬虫入门教程之图片篇

好,砸门先看一下这个网址的主页。

(1)小小白Python爬虫入门教程之图片篇

从网站页面上来看,壁纸在主页有好几个分类,什么最新啊精美啊热门啊…

这次呢,以最新壁纸为例

爬取的思路是:

  • 步骤一:获得最新壁纸这个大分类中的每个主题的网址
  • 步骤二:获得主题中图片的网址
  • 步骤三:获得图片的大图地址
  • 步骤四:保存图片,over

先贴上所有代码,后面会一步步解释。

from bs4 import BeautifulSoup
import requests
import os

url = 'http://www.zhuoku.com/'
header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'}
url_get = requests.get(url,headers = header)
url_decode = url_get.content.decode("gb2312","ignore").encode("utf-8","ignore") #gb2312为网页编码
url_soup = BeautifulSoup(url_decode,'html.parser')
all_a = url_soup.find('div',id="zuixin").find_all('a',attrs={"class":"title"}) #此处attrs={"class":"title"}必须为大括号
for a in all_a:
    title = a.get_text().replace('/','') #取得<a>标签中的text
    href = a.get('href') #取得<a>标签中的href
    img_url = url + href[1:-4] + '(1).htm' #补全herf
    if os.path.isdir(os.path.join("D:zhuoku",title)): #如果存在文件夹
        print('exist ' + title)
        pass #跳过
    else: #否则
        os.makedirs(os.path.join("D:zhuoku",title)) #创建文件夹
        print('makedir ' + title)
    os.chdir("D:zhuoku\"+title) #切换到此文件夹
    img_url_get = requests.get(img_url,headers = header)
    img_url_soup = BeautifulSoup(img_url_get.text,'html.parser')
    max_img_page = img_url_soup.find('div',id="yema").find_all('a')[-1].get_text() #[-1]表示find_all('a')中的最后一个
    for page in range(1, int(max_img_page)+1):
        jpg_href = url + href[1:-4] + '(' + str(page) + ').htm' + '#turn' #jpg网址
        jpg_href_get = requests.get(jpg_href,headers = header)
        jpg_soup = BeautifulSoup(jpg_href_get.text,'html.parser')
        jpg_url = jpg_soup.find('div',id="bizhiimg").find('img')['src'] #jpg网址中的图片文件地址
        name = jpg_url[-9:] #截取图片文件地址的倒数第9位至末尾为图片的名字
        if os.path.isfile(name): #如果存在名为name的文件
            print(name + ' exist skip')
            pass #下面全跳过
        else: #否则
            jpg_header = {
                    'Referer':jpg_href,
                    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'
                    }
            jpg = requests.get(jpg_url,headers = jpg_header) #jpg文件地址解析
            f = open(name, 'ab')
            f.write(jpg.content)
            print(name + ' saved')
            f.close()
print('congratulations! all finished!')

2.1,实现步骤一

2.1.2,获得网页源代码

代码如下

from bs4 import BeautifulSoup
import requests
import os

url = 'http://www.zhuoku.com/' #网址记得一定要加''号
header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'}
url_get = requests.get(url,headers = header)

代码解释,import部分:

requests模块,我们这次需要用到它来获取网页的源代码。

BeautifulSoup模块是一个可以从网页上提取数据的Python库,它包括在bs4模块中,所以写为 from bs4 import BeautifulSoup

os模块用来保存获取到的图片,后面需要用到。

这三个模块都已经包含在Anaconda3软件中了,不需要自己另外安装。

Headers是HTTP请求和相应的核心,它承载了关于客户端浏览器,请求页面,服务器等相关的信息。

(1)小小白Python爬虫入门教程之图片篇

其实最开始的几行也可以写成上图所示,在不加headers的情况下可以打开这个网址的主页,但是在很多其他的网站,没有headers的请求它就不给你返回数据,所以在这一步一般习惯上都加上了headers

上图第6行url_get 这一步,便是获取网页了。

当然,第5/6行的url,url_get,这几个字母只是我个人喜欢写成这样子,你可以按你喜好改

第7行print()便是输出括号中的结果,结果显示在右边。

但是后面为什么要加个.text呢,因为如果不加,显示的则是下图这样

(1)小小白Python爬虫入门教程之图片篇

输出的结果是<Response [200]>

这代表http请求正确的响应了,给你返回的一个状态码,但想要查看返回的网页源代码就得加.text

ok,成功获得网页源代码

2.1.2获得主题名称和主题网址。

最新壁纸下的主题右键,检查。

(1)小小白Python爬虫入门教程之图片篇

可以看出,最新壁纸这个分类在一个id=”zuixin”的<div>标签下。

壁纸主题在<div>标签下的<li>…</li>标签中,而<li>标签下有两个<a>标签。

而我们需要的主题网址和主题名称就包含在第二个<a>标签里面,所以这里我们就不需要理会<li>,直接寻找<div>下的<a>即可。

<a href=”/zhuomianbizhi/jingxuan-jingxuantaotu/20171014043134.htm” class=”title”>桌酷精选壁纸 2017/10/14</a>

上面可以视为:

<a href=”主题网址” class=”title”>主题名称</a>

所以代码可以写成:

url_soup = BeautifulSoup(url_get,'html.parser')
all_a = url_soup.find('div',id="zuixin").find_all('a',attrs={"class":"title"})
for a in all_a:
    print(a)

解释在下:

url_soup = BeautifulSoup(url_get,'html.parser')

这是BeautifulSoup的一个常用用法,具体可参看:BeautifulSoup的高级应用 之 find findAll

find('div',id="zuixin")

表示 寻找第一个 id=”zuixin”的div标签。

find('div',id="zuixin").find_all('a',attrs={"class":"title"})

表示 找到的 id=”zuixin”的div标签下 所有 class=”title”的a标签。

为什么第一个find里可以直接用id=”zuixin”,而第二个find需要用到attrs呢?因为…

有两种情况则要用到参数attrs:一是标签字符中带有-,比如data-custom;二是class不能看作标签属性,需要用attrs属性传递参数。

for a in all_a:

for…in…:代表一个循环,all_a里找到的所有放进这个循环,每次取出一个,直到循环结束。

记得末尾要加冒号。

好,我们来运行一下

(1)小小白Python爬虫入门教程之图片篇

成功获得了<a>标签,但!!!看右边输出部分…

为什么主题名称里的中文全是乱码!!!!!!!!!!!!

怎么办!!!

这里…

当初直接导致我放弃了N次

毕竟小白啊,不知道如何处理

还没有人教

在网上各种找答案,把代码抄过来改改用,没效果,骂了N多句cnm mmp,放弃…搁浅…

过了几天,不甘,,,继续找解决办法,,,没找到,又骂了N多句cnm mmp,放弃…搁浅…

………

……

皇天不负有心人

后来终于在这么一个地方,找到了答案python中requests爬去网页内容出现乱码的解决方案 – Winterto1990的博客 – CSDN博客

尼玛的!

都快哭了你知道吗!!!

查看网页源代码,在源代码第四行发现这个网站用的是gb2312,然后改代码,如下

(1)小小白Python爬虫入门教程之图片篇

图片看不清可以到本节开头看代码。

乱码问题终于得到解决。

接上面代码

for a in all_a:
    title = a.get_text()
    href = a.get('href')
    img_url = url[0:-1] + href

现在是处理<a>标签

<a href=”主题网址” class=”title”>主题名称</a>

解释在下:

a.get_text()表示取得<a>标签里的文字,也就是主题名称。

a.get(‘href’)表示取得href=撇号 里面的网址。

<a class=”title” href=”/zhuomianbizhi/jingxuan-jingxuantaotu/20171014043134.htm”>桌酷精选壁纸 2017/10/14</a>

可以看出取得的网址是不全的,需要补为完整的网址。

但是[0:-1]是什么意思呢?

因为,url为 zhuoku.com/

如果直接 + /zhuomianbizhi/jingxuan-jingxuantaotu/20171014043134.htm

最后网址就变成了zhuoku.com//zhuomianbiz

可以看到com后面有俩//,是个错误的网址

所以url[0:-1]便是截取url第一位至倒数第一位的字符,刚好去掉最后一个/,这样网址就正确了

更多用法可以参看这里:黄聪:Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等) – 黄聪 – 博客园

另外,你也可以写成如下:

img_url = 'http://www.zhuoku.com' + href

效果一样。

第一步代码合起来如下

from bs4 import BeautifulSoup
import requests
import os

url = 'http://www.zhuoku.com/'
header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'}
url_get = requests.get(url,headers = header)
url_decode = url_get.content.decode("gb2312","ignore").encode("utf-8","ignore") #gb2312为网页编码
url_soup = BeautifulSoup(url_decode,'html.parser')
all_a = url_soup.find('div',id="zuixin").find_all('a',attrs={"class":"title"}) #此处attrs={"class":"title"}必须为大括号
for a in all_a:
    title = a.get_text()
    href = a.get('href')
    img_url = url[0:-1] + href #补全herf

至此

步骤一已经完成!

2.2,实现步骤二

获得主题中图片的地址

好,以我们刚刚获得到的第一个主题的网址为例:

zhuoku.com/zhuomianbizh

(ps:为什么知乎总是自作主张的加上超链接?还不能取消?)

我们点进这个主题的图片看一下,发现图片网址似乎有什么规律

(1)小小白Python爬虫入门教程之图片篇

每个图片网址都是在步骤一中获得到的主题网址后面加上括号数字得到的,

我们把网页拉到最下面,发现底下就有页码。

如下图:

(1)小小白Python爬虫入门教程之图片篇

这就好办了

直接解析网页获得最大的页数,然后for循环从1遍历至175

这样就可以得到主题中所有的图片的网址,有了图片网址,我们就可以从中找到原大图的地址,保存原大图,也就实现了我们的目标。

查看源代码发现,所有的页码全在id=”yema”的<div>标签下的<li>标签下的<a>标签里…

<a href=”20171014043134(175).htm” title=”桌酷精选壁纸” 2017=”” 10=”” 14-第175页=””>175</a>

实现方法与步骤一中相同。

代码接上面的for,如下:

for a in all_a:
    title = a.get_text()
    href = a.get('href')
    img_url = url + href[1:-4] + '(1).htm' #补全为第一张图片的herf
    img_url_get = requests.get(img_url,headers = header)
    img_url_soup = BeautifulSoup(img_url_get.text,'html.parser')
    max_img_page = img_url_soup.find('div',id="yema").find_all('a')[-1].get_text() #[-1]表示find_all('a')中的最后一个

好,我们来运行一下

(1)小小白Python爬虫入门教程之图片篇

最大页数全出来了!

再把最大页数变为图片网址,接上面max_img_page,代码如下:

for page in range(1, int(max_img_page)+1):
        jpg_href = url + href[1:-4] + '(' + str(page) + ').htm' + '#turn'

还是for循环,从1遍历至max_img_page,jpg_href 为补全图片网址。

跑一个看看

(1)小小白Python爬虫入门教程之图片篇

恩,nice!

步骤二完成!

2.3,实现步骤三

获得图片的大图地址

随便找一个图片网址打开

zhuoku.com/zhuomianbizh.htm#turn

右键,检查,可以发现

(1)小小白Python爬虫入门教程之图片篇

scr中就是原始大图的地址,好,现在来获取scr中的原始大图地址

代码接上:

jpg_href_get = requests.get(jpg_href,headers = header)
        jpg_soup = BeautifulSoup(jpg_href_get.text,'html.parser')
        jpg_url = jpg_soup.find('div',id="bizhiimg").find('img')['src']

具体原理与上面讲的一样,其实这一步获取的源代码的中文还是乱码,但是这个乱码对我们无影响,所以无需理会。

运行一下试试看

(1)小小白Python爬虫入门教程之图片篇

恩,完美!

至此,步骤三完成!

到第三步为止,所有代码如下:

from bs4 import BeautifulSoup
import requests
import os

url = 'http://www.zhuoku.com/'
header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'}
url_get = requests.get(url,headers = header)
url_decode = url_get.content.decode("gb2312","ignore").encode("utf-8","ignore") #gb2312为网页编码
url_soup = BeautifulSoup(url_decode,'html.parser')
all_a = url_soup.find('div',id="zuixin").find_all('a',attrs={"class":"title"}) #此处attrs={"class":"title"}必须为大括号
for a in all_a:
    title = a.get_text()
    href = a.get('href')
    img_url = url + href[1:-4] + '(1).htm' #补全为第一张图片的href
    img_url_get = requests.get(img_url,headers = header)
    img_url_soup = BeautifulSoup(img_url_get.text,'html.parser')
    max_img_page = img_url_soup.find('div',id="yema").find_all('a')[-1].get_text() #[-1]表示find_all('a')中的最后一个
    for page in range(1, int(max_img_page)+1):
        jpg_href = url + href[1:-4] + '(' + str(page) + ').htm' + '#turn' #jpg网址
        jpg_href_get = requests.get(jpg_href,headers = header)
        jpg_soup = BeautifulSoup(jpg_href_get.text,'html.parser')
        jpg_url = jpg_soup.find('div',id="bizhiimg").find('img')['src']

2.4,实现步骤四

保存图片

先贴代码,大家可以比较一下与上面的有什么区别

from bs4 import BeautifulSoup
import requests
import os

url = 'http://www.zhuoku.com/'
header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'}
url_get = requests.get(url,headers = header)
url_decode = url_get.content.decode("gb2312","ignore").encode("utf-8","ignore") #gb2312为网页编码
url_soup = BeautifulSoup(url_decode,'html.parser')
all_a = url_soup.find('div',id="zuixin").find_all('a',attrs={"class":"title"}) #此处attrs={"class":"title"}必须为大括号
for a in all_a:
    title = a.get_text().replace('/','')
    href = a.get('href')
    os.makedirs(os.path.join("D:zhuoku",title))
    os.chdir("D:zhuoku\"+title)
    img_url = url + href[1:-4] + '(1).htm' #补全href
    img_url_get = requests.get(img_url,headers = header)
    img_url_soup = BeautifulSoup(img_url_get.text,'html.parser')
    max_img_page = img_url_soup.find('div',id="yema").find_all('a')[-1].get_text() #[-1]表示find_all('a')中的最后一个
    for page in range(1, int(max_img_page)+1):
        jpg_href = url + href[1:-4] + '(' + str(page) + ').htm' + '#turn' #jpg网址
        jpg_href_get = requests.get(jpg_href,headers = header)
        jpg_soup = BeautifulSoup(jpg_href_get.text,'html.parser')
        jpg_url = jpg_soup.find('div',id="bizhiimg").find('img')['src']
        name = jpg_url[-9:] #截取倒数第9位至末尾为图片的名字
        jpg = requests.get(jpg_url,headers = header)
        f = open(name, 'ab')
        f.write(jpg.content)
        print(name + '.jpg saved')
        f.close()

首先是在第一个for循环中,在取得title之后,加入了下面两行代码,

  os.makedirs(os.path.join("D:zhuoku",title)) #在D:zhuoku下建立名为title的文件夹
    os.chdir("D:zhuoku\"+title) #切换到此文件夹

细心地童鞋可能发现了,title那一行被我在末尾加了.replace(‘/’,”)

为什么呢?

因为有些title是这样的

桌酷精选壁纸 2017/10/14

title里有两个斜杠,这两个斜杠如果不去掉的话,结果会变成这样

D:zhuoku桌酷精选壁纸 20171014****.jpg

它会建立好多级文件夹,因为斜杠的原因。

replace的用法可以看这里:Python replace()方法

好,我们运行一下。

结果。。。

(1)小小白Python爬虫入门教程之图片篇

这是特么个啥!

被网站反爬虫了!

怎么办呢,这时候我们就需要修改header了,具体来说是在header里加入Referer

HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。

我们当然是从jpg_href过去的啦,所以改header,如下:

jpg_header = {
                'Referer':jpg_href,
                'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'
                }
        jpg = requests.get(jpg_url,headers = jpg_header)
        f = open(name, 'ab')
        f.write(jpg.content)
        print(name + '.jpg saved')
        f.close()

再运行,我擦!报错!

(1)小小白Python爬虫入门教程之图片篇

FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: ‘D:\zhuoku\桌酷精选壁纸 20171015’

上一步中已经创建了此文件夹,所以运行报错

怎么办呢,我们来加个判定吧,如果存在文件夹即跳过,如果不存在,则创建。

改代码:

   if os.path.isdir(os.path.join("D:zhuoku",title)): #如果存在文件夹
        print('exist ' + title)
        pass #跳过
    else: #否则
        os.makedirs(os.path.join("D:zhuoku",title)) #创建文件夹
        print('makedir ' + title)
    os.chdir("D:zhuoku\"+title)

其实这里的if与excel里的if差不多,如果正确则这样,如果错误则那样。

这里的print()算是给个提示,让我们知道进行到哪一步了。

既然这样,那么我们把创建jpg图片那一步也加个if判定把,存在则跳过,否则创建。

最后完整版代码如下:

from bs4 import BeautifulSoup
import requests
import os

url = 'http://www.zhuoku.com/'
header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'}
url_get = requests.get(url,headers = header)
url_decode = url_get.content.decode("gb2312","ignore").encode("utf-8","ignore") #gb2312为网页编码
url_soup = BeautifulSoup(url_decode,'html.parser')
all_a = url_soup.find('div',id="zuixin").find_all('a',attrs={"class":"title"}) #此处attrs={"class":"title"}必须为大括号
for a in all_a:
    title = a.get_text().replace('/','') #取得<a>标签中的text
    href = a.get('href') #取得<a>标签中的href
    img_url = url + href[1:-4] + '(1).htm' #补全herf
    if os.path.isdir(os.path.join("D:zhuoku",title)): #如果存在文件夹
        print('exist ' + title)
        pass #跳过
    else: #否则
        os.makedirs(os.path.join("D:zhuoku",title)) #创建文件夹
        print('makedir ' + title)
    os.chdir("D:zhuoku\"+title) #切换到此文件夹
    img_url_get = requests.get(img_url,headers = header)
    img_url_soup = BeautifulSoup(img_url_get.text,'html.parser')
    max_img_page = img_url_soup.find('div',id="yema").find_all('a')[-1].get_text() #[-1]表示find_all('a')中的最后一个
    for page in range(1, int(max_img_page)+1):
        jpg_href = url + href[1:-4] + '(' + str(page) + ').htm' + '#turn' #jpg网址
        jpg_href_get = requests.get(jpg_href,headers = header)
        jpg_soup = BeautifulSoup(jpg_href_get.text,'html.parser')
        jpg_url = jpg_soup.find('div',id="bizhiimg").find('img')['src'] #jpg网址中的图片文件地址
        name = jpg_url[-9:] #截取图片文件地址的倒数第9位至末尾为图片的名字
        if os.path.isfile(name): #如果存在名为name的文件
            print(name + ' exist skip')
            pass #下面全跳过
        else: #否则
            jpg_header = {
                    'Referer':jpg_href,
                    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36'
                    }
            jpg = requests.get(jpg_url,headers = jpg_header) #requests返回jpg二进制文件
            f = open(name, 'ab')
            f.write(jpg.content)
            print(name + ' saved')
            f.close()
print('congratulations! all finished!')

至此,教程完结!

撒花!

Python爬虫不用入门,直接上路即可。

本文来自投稿,不代表程序员编程网立场,如若转载,请注明出处:http://www.cxybcw.com/203874.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code