1. 程式人生 > >python網路爬蟲之解析網頁的正則表示式(爬取4k動漫圖片)[三]

python網路爬蟲之解析網頁的正則表示式(爬取4k動漫圖片)[三]

前言

hello,大家好

本章可是一個重中之重,因為我們今天是要爬取一個圖片而不是一個網頁或是一個json

所以我們也就不用用到selenium模組了,當然有興趣的同學也一樣可以使用selenium去爬取。

為了方便我們就用requests模組就夠了,因為夠快。。。

上章的課程傳送門:


[python網路爬蟲之入門[一]](https://www.cnblogs.com/liwangwang/p/11977110.html)
[python網路爬蟲之自動化測試工具selenium\[二\]](https://www.cnblogs.com/liwangwang/p/11977134.html)


理一下本章思路:

  1. 學習並掌握好正則表示式
  2. 使用正則表示式去分析網站來獲取特定資訊

一、正則表示式的學習

1、正則表示式的匹配工具

如果是學過正則表示式的卻不知道這個工具的話,那絕對是一個很大的遺憾。

這個也叫做貓頭鷹,

 

 

可能還有一些比較好用的工具把,但這個就已經夠用了,

下載路徑:

連結:https://pan.baidu.com/s/1g8Zn-CKopsnCjA_o9jS0TQ
提取碼:iq9s

2、正則表示式的樣式

本著大家好,我好的思想理念,所以我覺得給大家起一個匹配案例就行了,其他的正則自己可以慢慢看程式碼理解
放圖:

 

 使用regexbuddy做檢測:

 

 失敗案例

 

 在python中的一個測試

 

 

3、正則表示式的案例

"""
正則表示式

"""
import re

str = "[email protected]"

# 匹配所有郵箱
# f = re.match("^\w{4,20}@\w+\.com$",str)

# 匹配qq或163郵箱
# f = re.match("\w{4,20}@(qq|163)\.com",str)

# 匹配<div><span>python</span></div> \num方法
# str = "<div><span>python</span></div>"
# f = re.match("<([A-Za-z]+)><([A-Za-z]+)>.*</\\2></\\1>",str)

# 匹配<div><span>python</span></div> 起別名方法
str = "<div><span>python</span></div>"
f = re.match("<(?P<name1>[A-Za-z]+)><(?P<name2>[A-Za-z]+)>.*</(?P=name2)></(?P=name1)>",str)

# 2、match和search的區別
# str = "你好,123,現在線上人數為9999"
# f = re.match("\\d*",str)
# f = re.search(",\\d*",str)
# f = re.findall("\\d*",str)


# 3、貪婪與非貪婪  :加個?就行
# f = re.findall('src=".*"',str)
# f = re.findall('src=".*?"',str)

# 4、免寫轉義\\ : 加個r
# f = re.match(r"<([A-Za-z]+)><([A-Za-z]+)>.*</\2></\1>",str)

if f:
    print("匹配成功")
    print(f.group())
    # for i in f:
    #     print(i)
else:
    print("匹配失敗")

二、爬取網頁圖片

1、分析網頁

我們此次爬取的物件為http://pic.netbian.com/4kdongma

獲取指定的圖片檢視:

 

 

但是呢,一個展示圖片根本不能符合我們的要求,

所以我們點選進去看看:

 

 

F12檢索網頁程式碼;

 

 ok,我們檢視一下這個圖片路徑http://pic.netbian.com/uploads/allimg/180222/231102-151931226201f1.jpg

 

 

接下來就是去分析一個網頁的結構,確定好用什麼正則表示式才能準確的拿到a標籤的href,或者img標籤的src

這個非常重要,重要,重要!!

比如

 

 

 ok,一步一步的分析網頁結構:

 

 

 那麼接下來的那個點選進去之後的html路經,我們照樣可以通過這個方法訪問,解析

下面自己測試  

import requests
import re
from fake_useragent import UserAgent
ua = UserAgent(verify_ssl=False)
headers = {
    "Cookie": "__cfduid=d475437d729908631eff1e1d69f0314c81574259376; zkhanecookieclassrecord=%2C66%2C; Hm_lvt_526caf4e20c21f06a4e9209712d6a20e=1574259380,1574691901,1574734052; security_session_verify=ebb4b36dc44da23d2cdd02fa4650ae15; Hm_lpvt_526caf4e20c21f06a4e9209712d6a20e=1574735387"
    ,
    "User-Agent": ua.random
}

rep = requests.get("http://pic.netbian.com/4kdongman/index.html", headers=headers, verify=False)
rep.encoding="gbk"
# result = """<a href="(.*?)" target="_blank"><img src=".*?" alt=".*?" /><b>.*?</b></a>"""
# 拿一個正則表示式去匹配
# contents = re.findall(result, rep.text)

print(rep.text)
# for content in contents:
#     print(content)

2、獲取資料

我們先看一下圖解:

 

 

 

 全部程式碼

"""
爬取4k動漫圖片

"""
import requests
import time
import os
import re

from fake_useragent import UserAgent
ua = UserAgent(verify_ssl=False)



headers = {
    "Cookie": "__cfduid=d475437d729908631eff1e1d69f0314c81574259376; zkhanecookieclassrecord=%2C66%2C; Hm_lvt_526caf4e20c21f06a4e9209712d6a20e=1574259380,1574691901,1574734052; security_session_verify=645e98edf446fb2efa862d275906b0ba; Hm_lpvt_526caf4e20c21f06a4e9209712d6a20e=1574782670"
    ,
    "User-Agent": ua.random
}
# 獲取當前目錄
root = os.getcwd()

# range此引數可以自己更改,第幾頁到第幾頁
for page in range(0, 125):
    # 進入當前目錄
    os.chdir(root)
    # 建立資料夾
    os.mkdir(f"4k動漫的第{page+1}頁")

    # 改變當前檔案目錄
    os.chdir(f"4k動漫的第{page+1}頁")
    if page+1 == 1:
        url = f"http://pic.netbian.com/4kdongman/index.html"
    else:
        url = f"http://pic.netbian.com/4kdongman/index_{page + 1}.html"


    response = requests.get(url,headers=headers,verify=False)
    response.encoding="gbk"

    if response.status_code == 200 :
        result= """<a href="(.*?)" target="_blank"><img src=".*?" alt=".*?" /><b>.*?</b></a>"""
        # 拿一個正則表示式去匹配
        contents = re.findall(result,response.text)
        # 去遍歷所有的圖片
        for content in contents:
            path = content
            print(f"{path}正在進入html......")
            response2 = requests.get("http://pic.netbian.com"+path, headers=headers,verify=False)
            response2.encoding = "gbk"
            time.sleep(1)
            result2 = """<a href="" id="img"><img src="(.*?)" data-pic=".*?" alt="(.*?)" title=".*?"></a>"""
            contents2 = re.findall(result2, response2.text)
            for content2 in contents2:
                path2 = content2[0]
                name = content2[1]
                response3 = requests.get("http://pic.netbian.com"+path2, headers=headers,verify=False)
                # 儲存到本地
                with open(f"{name}.jpg","wb") as f:
                    f.write(response3.content)
                print(f"{name} : {path2} 儲存成功,等待1秒後繼續爬取")
                time.sleep(1)
    print(f"第{page + 1}頁抓取成功,,等待2秒後繼續爬取")
    time.sleep(2)

爬取妹子網的案例

這個案例來自於:https://blog.csdn.net/qq_33958297/article/details/89388556

爬取的網站:https://www.mzitu.com/

# -*- coding: utf-8 -*-
 
import requests
import os
from lxml import etree
from threading import *
from time import sleep
 
nMaxThread = 3  #這裡設定需要開啟幾條執行緒
ThreadLock = BoundedSemaphore(nMaxThread)
 
gHeads = {
    "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
}
 
class Meizitu(Thread):
    def __init__(self,url,title):
        Thread.__init__(self)
        self.url = url  #這裡的url在後面的referer中需要使用
        self.title = title
 
    def run(self):
        try:
            PhotoUrl,Page = self.GetPhotoUrlAndPageNum()
            if PhotoUrl and Page > 0:
                self.SavePhoto(PhotoUrl,Page)
        finally:
            ThreadLock.release()
 
    def GetPhotoUrlAndPageNum(self):
        html = requests.get(self.url,headers=gHeads)
        if html.status_code == 200:
            xmlContent = etree.HTML(html.text)
            PhotoUrl = xmlContent.xpath("//div[@class='main-image']/p/a/img/@src")[0][:-6] #01.jpg  正好是-6
            PageNum = xmlContent.xpath("//div[@class='pagenavi']/a[5]/span/text()")[0]
            return PhotoUrl,int(PageNum)
        else:
            return None,None
 
    def SavePhoto(self,url,page):
        savePath = "./photo/%s" % self.title
        if not os.path.exists(savePath):
            os.makedirs(savePath)
        for i in range(page):
            heads = {
                "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
                "Referer": "%s/%d" %(self.url,i+1),
                "Accept": "image/webp,image/apng,image/*,*/*;q=0.8"
            }
            j = 0
            while j<5:
                print (u"Download : %s/%d.jpg" % (self.title, i + 1))
                html = requests.get("%s%02d.jpg"%(url,i+1),headers=heads)
                if html.status_code == 200:
                    with open(savePath + "/%d.jpg"%(i+1),"wb") as f:
                        f.write(html.content)
                    break
                elif html.status_code == 404:
                    j+=1
                    sleep(0.05)
                    continue
                else:
                    return None
 
 
def main():
    while True:
        try:
            nNum = int(raw_input(u"請輸入要下載幾頁: "))
            if nNum>0:
                break
        except ValueError:
            print(u"請輸入數字。")
            continue
    for i in range(nNum):
        url = "https://www.mzitu.com/xinggan/page/%d/"%(i+1)
        html = requests.get(url,headers=gHeads)
        if html.status_code == 200:
            xmlContent = etree.HTML(html.content)
            hrefList = xmlContent.xpath("//ul[@id='pins']/li/a/@href")
            titleList = xmlContent.xpath("//ul[@id='pins']/li/a/img/@alt")
            for i in range(len(hrefList)):
                ThreadLock.acquire()
                t = Meizitu(hrefList[i],titleList[i])
                t.start()
 
 
if __name__ == '__main__':
    main()

後記

如果有正則基礎的可以直接看如何爬取,沒有的可以學一學。

不過regexbuddy工具都可以玩玩看

如果感覺本章寫的還不錯的話,不如。。。。。(~ ̄▽ ̄)~ ,(´▽`ʃ