中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python爬蟲入門【5】:27270圖片爬取

發布時間:2020-04-10 09:36:36 來源:網絡 閱讀:480 作者:學Python派森 欄目:編程語言

今天繼續爬取一個網站,http://www.27270.com/ent/meinvtupian/這個網站具備反爬,所以我們下載的代碼有些地方處理的也不是很到位,大家重點學習思路,有啥建議可以在評論的地方跟我說說。

Python爬蟲入門【5】:27270圖片爬取

為了以后的網絡請求操作方向,我們這次簡單的進行一些代碼的封裝操作。

這里在你可以先去安裝一個叫做retrying的模塊

pip install retrying

這個模塊的具體使用,自己去百度吧。嘿嘿噠?

在這里我使用了一個隨機產生USER_AGENT的方法


import requests
from retrying import retry
import random
import datetime

class R:

    def __init__(self,method="get",params=None,headers=None,cookies=None):
        # do something

    def get_headers(self):
        user_agent_list = [ \
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1" \
            "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", \
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", \
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", \
            "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", \
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", \
            "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", \
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", \
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", \
            "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
        ]
        UserAgent = random.choice(user_agent_list)
        headers = {'User-Agent': UserAgent}
        return headers
    #other code
Python資源分享qun 784758214 ,內有安裝包,PDF,學習視頻,這里是Python學習者的聚集地,零基礎,進階,都歡迎

retrying 最簡單的使用就是給你想不斷重試的方法加上裝飾器@retry

在這里,我希望網絡請求模塊嘗試3次之后,在報錯!

在同時R類初始化方法中增加一些必備的參數,你可以直接看下面的代碼

__retrying_requests方法為私有方法,根據其中get狀語從句:post方式進行邏輯判斷


import requests
from retrying import retry
import random
import datetime

class R:

    def __init__(self,method="get",params=None,headers=None,cookies=None):
        #do something

    def get_headers(self):
        # do something
    @retry(stop_max_attempt_number=3)
    def __retrying_requests(self,url):
        if self.__method == "get":
            response = requests.get(url,headers=self.__headers,cookies=self.__cookies,timeout=3)
        else:
            response = requests.post(url,params=self.__params,headers=self.__headers,cookies=self.__cookies,timeout=3)
        return response.content

    # other code

網絡請求的方法已經聲明完畢,報道查看并且response.content數據流

下面基于這個私有方法,增加一個獲取網絡文本的方法和一個獲取網絡文件的方法。同步完善類的初始化方法,在開發中發現,要我們爬取的|網頁編碼的英文gb2312所以還需要給某些方法增加一個編碼參數

import requests
from retrying import retry
import random
import datetime

class R:
    # 類的初始化方法
    def __init__(self,method="get",params=None,headers=None,cookies=None):
        self.__method = method
        myheaders = self.get_headers()
        if headers is not None:
            myheaders.update(headers)
        self.__headers = myheaders
        self.__cookies = cookies
        self.__params = params

    def get_headers(self):
       # do something

    @retry(stop_max_attempt_number=3)
    def __retrying_requests(self,url):
        # do something

    # get請求
    def get_content(self,url,charset="utf-8"):
        try:
            html_str = self.__retrying_requests(url).decode(charset)
        except:
            html_str = None
        return html_str

    def get_file(self,file_url):
        try:
            file = self.__retrying_requests(file_url)
        except:
            file = None
        return file

到此,這個R類已經被我們完善了,完整的代碼,你應該從上面拼湊起來,你也可以直接翻到文章最后面,去github上上直接查閱。

接下來,就是比較重要的爬蟲代碼部分了。這一次,我們可以簡單的使用一下類和對象,并且加上簡單的多線程操作。

首先,一個創建33 ImageList類,這個類第一件事情,需要獲取我們爬取頁面的總頁碼數目

Python爬蟲入門【5】:27270圖片爬取

這個步驟比較簡單

  1. 獲取網頁源碼
  2. 正則匹配末頁元素
  3. 提取數字
import http_help as hh   # 這個http_help 是我上面寫到的那個R類
import re
import threading
import time
import os
import requests

# 獲取所有待爬取的URL列表
class ImageList():
    def __init__(self):
        self.__start = "http://www.27270.com/ent/meinvtupian/list_11_{}.html"  # URL模板
        # 頭文件
        self.__headers = {"Referer":"http://www.27270.com/ent/meinvtupian/",
                          "Host":"www.27270.com"
                          }
        self.__res = hh.R(headers=self.__headers)  # 初始化訪問請求
    def run(self):
        page_count =  int(self.get_page_count())

        if page_count==0:
            return
        urls = [self.__start.format(i) for i in range(1,page_count)]
        return urls

    # 正則表達式匹配末頁,分析頁碼
    def get_page_count(self):
        # 注意這個地方需要傳入編碼
        content = self.__res.get_content(self.__start.format("1"),"gb2312")
        pattern = re.compile("<li><a href='list_11_(\d+?).html' target='_self'>末頁</a></li>")
        search_text = pattern.search(content)
        if search_text is not None:
            count = search_text.group(1)
            return count
        else:
            return 0
if __name__ == '__main__':
    img = ImageList()
    urls = img.run()

的上面代碼注意get_page_count方法,該方法已經獲取到了末尾的頁碼

Python爬蟲入門【5】:27270圖片爬取

在我們run方法內部,通過一個列表生成器

urls = [self.__start.format(i) for i in range(1,page_count)]

批量把要爬取的所有鏈接都生成完畢。

27270圖片----分析上面爬取到的URL列表,捕獲詳情頁

我們采用生產者和消費者模型,就是一個抓取鏈接圖片,一個下載圖片,采用多線程的方式進行操作,需要首先引入

import threading
import time

完整代碼如下

import http_help as hh
import re
import threading
import time
import os
import requests

urls_lock = threading.Lock()  #url操作鎖
imgs_lock = threading.Lock()  #圖片操作鎖

imgs_start_urls = []

class Product(threading.Thread):
    # 類的初始化方法
    def __init__(self,urls):
        threading.Thread.__init__(self)
        self.__urls = urls
        self.__headers = {"Referer":"http://www.27270.com/ent/meinvtupian/",
                          "Host":"www.27270.com"
                          }

        self.__res = hh.R(headers=self.__headers)

    # 鏈接抓取失敗之后重新加入urls列表中
    def add_fail_url(self,url):
        print("{}該URL抓取失敗".format(url))
        global urls_lock
        if urls_lock.acquire():
            self.__urls.insert(0, url)
            urls_lock.release()  # 解鎖

    # 線程主要方法
    def run(self):
        print("*"*100)
        while True:
            global urls_lock,imgs_start_urls
            if len(self.__urls)>0:
                if urls_lock.acquire():   # 鎖定
                    last_url = self.__urls.pop()   # 獲取urls里面最后一個url,并且刪除
                    urls_lock.release()  # 解鎖

                print("正在操作{}".format(last_url))

                content = self.__res.get_content(last_url,"gb2312")   # 頁面注意編碼是gb2312其他格式報錯
                if content is not  None:
                    html = self.get_page_list(content)

                    if len(html) == 0:
                        self.add_fail_url(last_url)
                    else:
                        if imgs_lock.acquire():
                            imgs_start_urls.extend(html)    # 爬取到圖片之后,把他放在待下載的圖片列表里面
                            imgs_lock.release()

                    time.sleep(5)
                else:
                    self.add_fail_url(last_url)

            else:
                print("所有鏈接已經運行完畢")
                break

    def get_page_list(self,content):
        # 正則表達式
        pattern = re.compile('<li> <a href="(.*?)" title="(.*?)" class="MMPic" target="_blank">.*?</li>')
        list_page = re.findall(pattern, content)

        return list_page
Python資源分享qun 784758214 ,內有安裝包,PDF,學習視頻,這里是Python學習者的聚集地,零基礎,進階,都歡迎

上述代碼中比較重要的有
threading.Lock()鎖的使用,在多個線程之間操作全局變量,需要進行及時的鎖定;
其他的注意內容,我已經添加在注釋里面,只要你按著步驟一點點的寫,并且加入一些自己微妙的理解,就可以搞定。

到現在為止,我們已經抓取到了所有的圖片地址,把我他存放在了一個全局的變量里面imgs_start_urls
那么現在又來了

這個列表里面存放的是http://www.27270.com/ent/meinvtupian/2018/298392.html這樣的地址,當你打開這個頁面之后,你會發現只有一張圖片,并且下面有個分頁。

Python爬蟲入門【5】:27270圖片爬取

Python爬蟲入門【5】:27270圖片爬取

點擊分頁之后,就知道規律了

http://www.27270.com/ent/meinvtupian/2018/298392.html 
http://www.27270.com/ent/meinvtupian/2018/298392_2.html 
http://www.27270.com/ent/meinvtupian/2018/298392_3.html 
http://www.27270.com/ent/meinvtupian/2018/298392_4.html 
....

當你進行多次嘗試之后,你會發現,后面的鏈接完全可以靠拼接完成,如果沒有這個頁面,那么他會顯示?

Python爬蟲入門【5】:27270圖片爬取

好了,如果你進行了上面的操作,你應該知道接下來怎么實現啦!

我把所有的代碼,都直接貼在下面,還是用注釋的方式給大家把最重要的地方標注出來

class Consumer(threading.Thread):
    # 初始化
    def __init__(self):
        threading.Thread.__init__(self)
        self.__headers = {"Referer": "http://www.27270.com/ent/meinvtupian/",
                          "Host": "www.27270.com"}
        self.__res = hh.R(headers=self.__headers)

    # 圖片下載方法
    def download_img(self,filder,img_down_url,filename):
        file_path = "./downs/{}".format(filder)

        # 判斷目錄是否存在,存在創建
        if not os.path.exists(file_path):
            os.mkdir(file_path)  # 創建目錄

        if os.path.exists("./downs/{}/{}".format(filder,filename)):
            return
        else:
            try:
                # 這個地方host設置是個坑,因為圖片為了防止盜鏈,存放在另一個服務器上面
                img = requests.get(img_down_url,headers={"Host":"t2.hddhhn.com"},timeout=3)
            except Exception as e:
                print(e)

            print("{}寫入圖片".format(img_down_url))
            try:
                # 圖片寫入不在贅述
                with open("./downs/{}/{}".format(filder,filename),"wb+") as f:
                    f.write(img.content)
            except Exception as e:
                print(e)
                return

    def run(self):

        while True:
            global imgs_start_urls,imgs_lock

            if len(imgs_start_urls)>0:
                if imgs_lock.acquire():  # 鎖定
                    img_url = imgs_start_urls[0]   #獲取到鏈接之后
                    del imgs_start_urls[0]  # 刪掉第0項
                    imgs_lock.release()  # 解鎖
            else:
                continue

            # http://www.27270.com/ent/meinvtupian/2018/295631_1.html

            #print("圖片開始下載")
            img_url = img_url[0]
            start_index = 1
            base_url = img_url[0:img_url.rindex(".")]    # 字符串可以當成列表進行切片操作

            while True:

                img_url ="{}_{}.html".format(base_url,start_index)   # url拼接
                content = self.__res.get_content(img_url,charset="gbk")   # 這個地方獲取內容,采用了gbk編碼
                if content is not None:
                    pattern = re.compile('<div class="articleV4Body" id="picBody">[\s\S.]*?img alt="(.*?)".*? src="(.*?)" />')
                    # 匹配圖片,匹配不到就代表本次操作已經完畢
                    img_down_url = pattern.search(content)  # 獲取到了圖片地址

                    if img_down_url is not None:
                        filder = img_down_url.group(1)
                        img_down_url = img_down_url.group(2)
                        filename = img_down_url[img_down_url.rindex("/")+1:]
                        self.download_img(filder,img_down_url,filename)  #下載圖片

                    else:
                        print("-"*100)
                        print(content)
                        break # 終止循環體

                else:
                    print("{}鏈接加載失敗".format(img_url))

                    if imgs_lock.acquire():  # 鎖定
                        imgs_start_urls.append(img_url)
                        imgs_lock.release()  # 解鎖

                start_index+=1   # 上文描述中,這個地方需要不斷進行+1操作

所有的代碼都在上面了,關鍵的地方我盡量加上了標注,你可以細細的看一下,實在看不明白,就多敲幾遍,因為沒有特別復雜的地方,好多都是邏輯。

Python爬蟲入門【5】:27270圖片爬取

最后附上主要部分的代碼,讓我們的代碼跑起來


if __name__ == '__main__':

    img = ImageList()
    urls = img.run()
    for i in range(1,2):
        p = Product(urls)
        p.start()

    for i in range(1,2):
        c = Consumer()
        c.start()
Python資源分享qun 784758214 ,內有安裝包,PDF,學習視頻,這里是Python學習者的聚集地,零基礎,進階,都歡迎

一會過后,就慢慢收圖吧

Python爬蟲入門【5】:27270圖片爬取

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

昌平区| 日土县| 台中市| 炉霍县| 游戏| 康马县| 潼关县| 青海省| 蒙山县| 株洲市| 保亭| 湖南省| 伊金霍洛旗| 营口市| 阆中市| 凌源市| 罗定市| 武威市| 刚察县| 宁陕县| 铜川市| 抚宁县| 乐亭县| 搜索| 定州市| 桃园县| 九寨沟县| 林芝县| 郴州市| 荥阳市| 廊坊市| 广宁县| 逊克县| 桓仁| 五华县| 北海市| 根河市| 临高县| 衡南县| 杭锦后旗| 蓬安县|