Python爬虫入门教程 2-100 妹子图网站爬取

妹子图网站—-媒介

从本日最先就要撸起袖子,直接写Python爬虫了,进修言语最好的要领就是有目标的举行,所以,接下来我将用10+篇的博客,写爬图片这一件事变。愿望能够做好。

为了写好爬虫,我们需要预备一个火狐浏览器,还需要预备抓包东西,抓包东西,我运用的是CentOS自带的tcpdump,加上wireshark ,这两款软件的装置和运用,发起你照样进修一下,背面我们应该会用到。

妹子图网站—- 收集要求模块requests

Python中的大批开源的模块使得编码变的迥殊简朴,我们写爬虫第一个要相识的模块就是requests。

妹子图网站—- 装置requests

翻开终端:运用敕令

pip3 install requests

守候装置终了即可运用

接下来在终端中键入以下敕令

# mkdir demo  
# cd demo
# touch down.py

上面的linux敕令是 建立一个名称为demo的文件夹,今后建立一个down.py文件,你也能够运用GUI东西,像操纵windows一样,右键建立种种文件。

为了进步在linux上的开辟效力,我们需要装置一个visual studio code 的开辟东西

关于怎样装置vscode,参考官方的https://code.visualstudio.com… 有细致的申明。

关于centos则以下:

sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
sudo sh -c 'echo -e "

\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com/yumrepos/vscode\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/vscode.repo'

然后用yum敕令装置

yum check-update
sudo yum install code

装置胜利今后,在你的CentOS中会涌现以下画面

《Python爬虫入门教程 2-100 妹子图网站爬取》

接着说我们上面的操纵 ,因为我们这边是用gnome图形界面,所以背面的有些操纵,我直接用windows的操纵作风讲解了

翻开软件>文件>翻开文件>找到我们方才建立的down.py文件

今后,在VSCODE内里输入


import requests   #导入模块

def run():        #声明一个run要领
    print("跑码文件")    #打印内容

if __name__ == "__main__":   #主顺序进口
    run()    #挪用上面的run要领
        

tips:本教程不是Python3的基本入门课,所以有些编码基本,默许你懂,比方Python没有分号末端,需要对齐花样。我会只管把解释写的完全

按键盘上的ctrl+s保留文件,假如提醒权限不足,那末根据提醒输入暗码即可

经由过程终端进入demo目次,然后输入

python3 down.py

显现以下效果,代表编译没有题目

[root@bogon demo]# python3 down.py
跑码文件

接下来,我们最先测试requests模块是不是能够运用

修正上述代码中的


import requests

def run():
    response = requests.get("http://www.baidu.com")
    print(response.text)

if __name__ == "__main__":
    run()
        

运转效果(涌现下图代表你运转胜利了):

《Python爬虫入门教程 2-100 妹子图网站爬取》

接下来,我们现实下载一张图片尝尝,比以下面这张图片

《Python爬虫入门教程 2-100 妹子图网站爬取》

修正代码,在这之前,我们修正一些内容

因为每次修正文件,都提醒必需管理员权限,所以你能够运用linux敕令修正权限。

[root@bogon linuxboy]# chmod -R 777 demo/


import requests

def run():
    response = requests.get("http://www.newsimg.cn/big201710leaderreports/xibdj20171030.jpg") 
    with open("a.jpg","wb") as f :
        f.write(response.content)   
        f.close

if __name__ == "__main__":
    run()

运转代码今后,发如今文件夹内部生成了一个文件

《Python爬虫入门教程 2-100 妹子图网站爬取》

然则翻开文件今后发明,这个文件并不能查阅,这代表这个文件压根没有下载下来

《Python爬虫入门教程 2-100 妹子图网站爬取》

我们继续修正代码,因为有的服务器图片,都做了一些限定,我们能够用浏览器翻开,然则运用Python代码并不能完全的下载下来。

修正代码


import requests

def run():
    # 头文件,header是字典范例
    headers = {
        "Host":"www.newsimg.cn",
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5383.400 QQBrowser/10.0.1313.400"
    }
    response = requests.get("http://www.newsimg.cn/big201710leaderreports/xibdj20171030.jpg",headers=headers) 
    with open("a.jpg","wb") as f :
        f.write(response.content)   
        f.close()

if __name__ == "__main__":
    run()
        

好了,此次在终端编译一下python文件

python3 down.py

发明图片下载下来了

《Python爬虫入门教程 2-100 妹子图网站爬取》

我们重点检察上述代码中 requests.get部份,增加了一个headers的实参。如许我们顺序就下载下来了完全的图片。

妹子图网站---- Python爬虫页面剖析

有了上面这个简朴的案例,我们接下来的操纵就变的简朴多了。爬虫是怎样举行的呢?

输入域名->下载源代码->剖析图片途径->下载图片

上面就是他的步骤

输入域名

我们本日要爬的网站叫做 http://www.meizitu.com/a/pure...

为啥爬取这个网站,因为好爬。

好了,接下来剖析这个页面

《Python爬虫入门教程 2-100 妹子图网站爬取》

做爬虫很主要的一点,就是你要找到分页的处所,因为有分页代表着有规律,有规律,我们就好爬了(能够做的更智能一些,输入首页网址,爬虫本身就可以剖析到这个网站中的一切地点)

上面图片中,我们发清楚明了分页,那末找规律吧

《Python爬虫入门教程 2-100 妹子图网站爬取》

运用火狐浏览器的开辟者东西,发明分页规律

http://www.meizitu.com/a/pure_1.html
http://www.meizitu.com/a/pure_2.html
http://www.meizitu.com/a/pure_3.html
http://www.meizitu.com/a/pure_4.html

好了,接下来用Python完成这部份(以下写法有部份面向对象的写法,没有基本的同砚,请百度找些基本来看,不过关于想进修的你来讲,这些简朴极了)


import requests
all_urls = []  #我们拼接好的图片集和列表途径
class Spider():
    #组织函数,初始化数据运用
    def __init__(self,target_url,headers):
        self.target_url = target_url
        self.headers = headers

    #猎取一切的想要抓取的URL
    def getUrls(self,start_page,page_num):
        
        global all_urls
        #轮回获得URL
        for i in range(start_page,page_num+1):
            url = self.target_url  % i
            all_urls.append(url)

if __name__ == "__main__":
    headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
            'HOST':'www.meizitu.com'
    }
    target_url = 'http://www.meizitu.com/a/pure_%d.html' #图片集和列表划定规矩
    
    spider = Spider(target_url,headers)
    spider.getUrls(1,16)
    print(all_urls)
        

上面的代码,能够需要有肯定的Python基本能够看懂,不过你实在细致看一下,就几个要点

第一个是 class Spider(): 我们声清楚明了一个类,然后我们运用 def __init__去声明一个组织函数,这些我以为你找个教程30分钟也就学会了。

拼接URL,我们能够用许多要领,我这里用的是最直接的,字符串拼接。

注重上述代码中有一个全局的变量 all_urls 我用它来存储我们的一切分页的URL

接下来,是爬虫最中心的部份代码了

我们需要剖析页面中的逻辑。起首翻开 http://www.meizitu.com/a/pure... ,右键检察元素。

《Python爬虫入门教程 2-100 妹子图网站爬取》

《Python爬虫入门教程 2-100 妹子图网站爬取》

发明上图赤色框框内里的链接

点击图片今后,发明进入一个图片概况页面,发明竟然是一组图片,那末如今的题目是

我们要处置惩罚第一步,需要在 http://www.meizitu.com/a/pure... 这类页面中爬取一切的 http://www.meizitu.com/a/5585... 这类地点

这里我们采纳多线程的体式格局爬取(这里还用了一种设想形式,叫观察者形式)

import threading   #多线程模块
import re #正则表达式模块
import time #时刻模块

起首引入三个模块,离别是多线程,正则表达式,时刻模块

新增添一个全局的变量,而且因为是多线程操纵,我们需要引入线程锁

all_img_urls = []       #图片列表页面的数组

g_lock = threading.Lock()  #初始化一个锁  

声明一个生产者的类,用来不停的猎取图片概况页地点,然后增加到 all_img_urls 这个全局变量中


#生产者,担任从每一个页面提取图片列表链接
class Producer(threading.Thread):   

    def run(self):
        headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
            'HOST':'www.meizitu.com'
        }
        global all_urls
        while len(all_urls) > 0 :
            g_lock.acquire()  #在接见all_urls的时刻,需要运用锁机制
            page_url = all_urls.pop()   #经由过程pop要领移除末了一个元素,而且返回该值
            
            g_lock.release() #运用完成今后实时把锁给开释,轻易其他线程运用
            try:
                print("剖析"+page_url)   
                response = requests.get(page_url , headers = headers,timeout=3)
                all_pic_link = re.findall('<a target=\'_blank\' href="(.*?)">',response.text,re.S)   
                global all_img_urls
                g_lock.acquire()   #这里另有一个锁
                all_img_urls += all_pic_link   #这个处所注重数组的拼接,没有用append直接用的+=也算是python的一个新语法吧
                print(all_img_urls)
                g_lock.release()   #开释锁
                time.sleep(0.5)
            except:
                pass

上述代码用到了继续的观点,我从threading.Thread中继续了一个子类,继续的基本进修,你能够去翻翻 http://www.runoob.com/python3... 菜鸟教程就行。

线程锁,在上面的代码中,当我们操纵all_urls.pop()的时刻,我们是不愿望其他线程对他举行同时操纵的,不然会涌现意外,所以我们运用g_lock.acquire()锁定资本,然后运用完成今后,记着肯定要立马开释g_lock.release(),不然这个资本就一向被占用着,顺序没法举行下去了。

婚配网页中的URL,我运用的是正则表达式,背面我们会运用其他的要领,举行婚配。

re.findall() 要领是猎取一切婚配到的内容,正则表达式,你能够找一个30分钟入门的教程,看看就行。

代码轻易失足的处所,我放到了

try: except: 内里,固然,你也能够自定义毛病。

假如上面的代码,都没有题目,那末我们就可以够在顺序进口的处所编写

for x in range(2):
    t = Producer()
    t.start()
        

实行顺序,因为我们的Producer继续自threading.Thread类,所以,你必需要完成的一个要领是 def run 这个我置信在上面的代码中,你已看到了。然后我们能够实行啦~~~

运转效果:

《Python爬虫入门教程 2-100 妹子图网站爬取》

如许,图片概况页面的列表就已被我们存储起来了。

接下来,我们需要实行如许一步操纵,我想要守候图片概况页面悉数猎取终了,在举行接下来的剖析操纵。

这里增添代码

#threads= []   
#开启两个线程去接见
for x in range(2):
    t = Producer()
    t.start()
    #threads.append(t)

# for tt in threads:
#     tt.join()

print("举行到我这里了")

解释症结代码,运转以下

[linuxboy@bogon demo]$ python3 down.py
剖析http://www.meizitu.com/a/pure_2.html
剖析http://www.meizitu.com/a/pure_1.html
举行到我这里了
['http://www.meizitu.com/a/5585.html', 

把上面的tt.join等代码解释翻开

[linuxboy@bogon demo]$ python3 down.py
剖析http://www.meizitu.com/a/pure_2.html
剖析http://www.meizitu.com/a/pure_1.html
['http://www.meizitu.com/a/5429.html', ......
举行到我这里了

发明一个实质的区分,就是,我们因为是多线程的顺序,所以,当顺序跑起来今后,print("举行到我这里了")不会比及其他线程完毕,就会运转到,然则当我们改形成上面的代码今后,也就是加入了症结的代码 tt.join() 那末主线程的代码会比及所以子线程运转终了今后,在接着向下运转。这就满足了,我适才说的,先猎取到一切的图片概况页面的鸠合,这一前提了。

join所完成的事情就是线程同步,即主线程遇到join今后进入阻塞状态,一向守候其他的子线程实行完毕今后,主线程在继续实行。这个人人在今后能够经常会遇到。

下面编写一个消费者/观察者,也就是不停关注适才我们猎取的那些图片概况页面的数组。

增加一个全局变量,用来存储猎取到的图片链接

pic_links = []            #图片地点列表
#消费者
class Consumer(threading.Thread) : 
    def run(self):
        headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
            'HOST':'www.meizitu.com'
        }
        global all_img_urls   #挪用全局的图片概况页面的数组
        print("%s is running " % threading.current_thread)
        while len(all_img_urls) >0 : 
            g_lock.acquire()
            img_url = all_img_urls.pop()
            g_lock.release()
            try:
                response = requests.get(img_url , headers = headers )
                response.encoding='gb2312'   #因为我们挪用的页面编码是GB2312,所以需要设置一下编码
                title = re.search('<title>(.*?) | 妹子图</title>',response.text).group(1)
                all_pic_src = re.findall('<img alt=.*?src="(.*?)" /><br />',response.text,re.S)
                
                pic_dict = {title:all_pic_src}   #python字典
                global pic_links
                g_lock.acquire()
                pic_links.append(pic_dict)    #字典数组
                print(title+" 猎取胜利")
                g_lock.release()
                
            except:
                pass
            time.sleep(0.5)

看到没有,上面的代码实在和我们适才写的极为类似,背面,我会在github上面把这部份代码修正的越发简约一些,不过这才是第二课,背面我们的路长着呢。

代码中比较主要的一些部份,我已运用解释写好了,人人能够直接参考。人人肯定要注重我上面运用了两个正则表达式,离别用来婚配title和图片的url这个title是为了背面建立差别的文件夹运用的,所以人人注重吧。

#开启10个线程去猎取链接
for x in range(10):
    ta = Consumer()
    ta.start()

运转效果:

[linuxboy@bogon demo]$ python3 down.py
剖析http://www.meizitu.com/a/pure_2.html
剖析http://www.meizitu.com/a/pure_1.html
['http://www.meizitu.com/a/5585.html', ......
<function current_thread at 0x7f7caef851e0> is running 
<function current_thread at 0x7f7caef851e0> is running 
<function current_thread at 0x7f7caef851e0> is running 
<function current_thread at 0x7f7caef851e0> is running 
<function current_thread at 0x7f7caef851e0> is running 
<function current_thread at 0x7f7caef851e0> is running 
<function current_thread at 0x7f7caef851e0> is running 
<function current_thread at 0x7f7caef851e0> is running 
举行到我这里了
<function current_thread at 0x7f7caef851e0> is running 
<function current_thread at 0x7f7caef851e0> is running 
纯洁美如画,摄影师的御用麻豆 猎取胜利
宅男女神恭弘=叶 恭弘梓萱近日拍摄一组火爆写真 猎取胜利
美(bao)胸(ru)女王带来礼服引诱 猎取胜利
天天睁开眼看到优美的你,就是幸运 猎取胜利
可爱女孩,愿暖风庇护单纯和固执 猎取胜利
纯洁妹子如一缕阳光暖和这个冬季 猎取胜利 .....

是不是是觉得间隔胜利有进了一大步

接下来就是,我们开篇提到的谁人存储图片的操纵了,照样一样的步骤,写一个自定义的类

class DownPic(threading.Thread) :

    def run(self):
        headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
            'HOST':'mm.chinasareview.com'
        
        }
        while True:   #  这个处所写成死轮回,为的是不停监控图片链接数组是不是更新
            global pic_links
            # 上锁
            g_lock.acquire()
            if len(pic_links) == 0:   #假如没有图片了,就解锁
                # 不论什么情况,都要开释锁
                g_lock.release()
                continue
            else:
                pic = pic_links.pop()
                g_lock.release()
                # 遍历字典列表
                for key,values in  pic.items():
                    path=key.rstrip("\\")
                    is_exists=os.path.exists(path)
                    # 推断效果
                    if not is_exists:
                        # 假如不存在则建立目次
                        # 建立目次操纵函数
                        os.makedirs(path) 
                
                        print (path+'目次建立胜利')
                        
                    else:
                        # 假如目次存在则不建立,并提醒目次已存在
                        print(path+' 目次已存在') 
                    for pic in values :
                        filename = path+"/"+pic.split('/')[-1]
                        if os.path.exists(filename):
                            continue
                        else:
                            response = requests.get(pic,headers=headers)
                            with open(filename,'wb') as f :
                                f.write(response.content)
                                f.close

我们猎取图片链接今后,就需要下载了,我上面的代码是起首建立了一个之前猎取到title的文件目次,然后在目次内里经由过程下面的代码,去建立一个文件。

涉及到文件操纵,引入一个新的模块

import os  #目次操纵模块
# 遍历字典列表
for key,values in  pic.items():
    path=key.rstrip("\\")
    is_exists=os.path.exists(path)
    # 推断效果
    if not is_exists:
        # 假如不存在则建立目次
        # 建立目次操纵函数
        os.makedirs(path) 

        print (path+'目次建立胜利')
        
    else:
        # 假如目次存在则不建立,并提醒目次已存在
        print(path+' 目次已存在') 
    for pic in values :
        filename = path+"/"+pic.split('/')[-1]
        if os.path.exists(filename):
            continue
        else:
            response = requests.get(pic,headers=headers)
            with open(filename,'wb') as f :
                f.write(response.content)
                f.close

因为我们的图片链接数组,内里寄存是的字典花样,也就是下面这类花样


[{"妹子图1":["http://mm.chinasareview.com/wp-content/uploads/2016a/08/24/01.jpg","http://mm.chinasareview.com/wp-content/uploads/2016a/08/24/02.jpg"."http://mm.chinasareview.com/wp-content/uploads/2016a/08/24/03.jpg"]},{"妹子图2":["http://mm.chinasareview.com/wp-content/uploads/2016a/08/24/01.jpg","http://mm.chinasareview.com/wp-content/uploads/2016a/08/24/02.jpg"."http://mm.chinasareview.com/wp-content/uploads/2016a/08/24/03.jpg"]},{"妹子图3":["http://mm.chinasareview.com/wp-content/uploads/2016a/08/24/01.jpg","http://mm.chinasareview.com/wp-content/uploads/2016a/08/24/02.jpg"."http://mm.chinasareview.com/wp-content/uploads/2016a/08/24/03.jpg"]}]

需要先轮回第一层,猎取title,建立目次今后,在轮回第二层去下载图片,代码中,我们在修正一下,把非常处置惩罚增加上。

try:
    response = requests.get(pic,headers=headers)
    with open(filename,'wb') as f :
        f.write(response.content)
        f.close
except Exception as e:
    print(e)
    pass

然后在主顺序中编写代码


#开启10个线程保留图片
for x in range(10):
    down = DownPic()
    down.start()
        

运转效果:


[linuxboy@bogon demo]$ python3 down.py
剖析http://www.meizitu.com/a/pure_2.html
剖析http://www.meizitu.com/a/pure_1.html
['http://www.meizitu.com/a/5585.html', 'http://www.meizitu.com/a/5577.html', 'http://www.meizitu.com/a/5576.html', 'http://www.meizitu.com/a/5574.html', 'http://www.meizitu.com/a/5569.html', .......
<function current_thread at 0x7fa5121f2268> is running 
<function current_thread at 0x7fa5121f2268> is running 
<function current_thread at 0x7fa5121f2268> is running 
举行到我这里了
纯洁妹子如一缕阳光暖和这个冬季 猎取胜利
纯洁妹子如一缕阳光暖和这个冬季目次建立胜利
可爱女孩,愿暖风庇护单纯和固执 猎取胜利
可爱女孩,愿暖风庇护单纯和固执目次建立胜利
超美,纯纯的你与蓝蓝的天相得益彰 猎取胜利
超美,纯纯的你与蓝蓝的天相得益彰目次建立胜利
优美冻人,雪地里的跆拳道少女 猎取胜利
五官细腻的美眉,似乎童话里的公主 猎取胜利
有自信诱人的笑颜,天天都是绚烂的 猎取胜利
五官细腻的美眉,似乎童话里的公主目次建立胜利
有自信诱人的笑颜,天天都是绚烂的目次建立胜利
纯洁美如画,摄影师的御用麻豆 猎取胜利

文件目次下面同时涌现

《Python爬虫入门教程 2-100 妹子图网站爬取》

点开一个目次

《Python爬虫入门教程 2-100 妹子图网站爬取》

好了,本日的一个简朴的爬虫成了

末了我们在代码的头部写上

# -*- coding: UTF-8 -*-   

防备涌现 Non-ASCII character 'xe5' in file报错题目。

迎接关注「非本科顺序员」 复兴 【妹子图】猎取资本

    原文作者:梦想橡皮擦
    原文地址: https://segmentfault.com/a/1190000019243929
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞