天天看點

Python快速爬取車标網圖檔,以後不要說這什麼車你不認識了!

知識不分邊界......

人,為什麼要讀書?舉個例子:

當看到天邊飛鳥,你會說:“落霞與孤鹜齊飛,秋水共長天一色。”而不是:“卧靠,好多鳥。”;

當你失戀時你低吟淺唱道:“人生若隻如初見,何事秋風悲畫扇。”而不是千萬遍地悲喊:“藍瘦,香菇!”

今天回家早,陪倆小爺在樓下遛彎,忽然聽見一陣馬達轟鳴聲,嗖~~閃一輛跑車,大大問;“爸爸,這是什麼車啊?” 我:“紅色的車…”小小說:“爸爸肯定不認識,我也知道是紅色的車。”氣氛有些冷場…

别人看車關注牌子,我看車關注寬敞不,睡着舒服不?可不管怎樣不能在孩子面前丢份啊,我決定學習學習車标!

車标網

在網上找了半天車标的資料,最後看到了這個網站:車标網:http://www.chebiaow.com/logo。

Python快速爬取車标網圖檔,以後不要說這什麼車你不認識了!

網站将車系按照字母從A-Z進行了排序,然後點選每個車标進入詳細資訊,那Audi做例子:

Python快速爬取車标網圖檔,以後不要說這什麼車你不認識了!

有用的資料是哪些?品牌名稱,車标,成立時間,主要車型,官網…

那麼今天的爬蟲練習呼之欲出,擷取車标網下所有的汽車品牌及車标,并入庫儲存…

資料庫操作指南

針對簡單的資料,我習慣用python自帶的sqlite3進行資料庫的存儲,簡單友善….那麼如何管理我們的資料庫呢?推薦使用DBUtils!在往期的文章

決戰聯考,幫你秒變成語之王中,有對DBUtils的詳細介紹,這裡就不再贅述了…

但本次有一個知識點,我們需要将車标圖檔,存儲在資料庫中,那麼如何在資料庫中存儲圖檔,使用類型BLOB。舉一個簡單的資料庫圖檔讀寫例子

# -*- coding: utf-8 -*-
# @Author   : 王翔
# @JianShu  : 清風Python
# @Date     : 2019/7/22 23:00
# @Software : PyCharm
# @version  :Python 3.7.3
# @File     : show.py
import sqlite3
db = sqlite3.connect('Car.db')
cur = db.cursor()
cur.execute("CREATE TABLE if not exists image_save (image BLOB);")
with open('Audi.jpg', 'rb') as f:
    cur.execute("insert into image_save values(?)", (sqlite3.Binary(f.read()),))
    db.commit()
cur.execute('select image from image_save limit 1')
b = cur.fetchone()[0]
with open('1.jpg', 'wb') as f:
    f.write(b)      

我們建立一個image_save的測試表,然後将圖檔讀取為二進制位元組的方式,通過sqlite3.Binary将二進制檔案存儲至資料庫。

那麼同樣的,我們将BLOB類型的圖檔讀取出來後,進行寫入,即可達到效果,來看看這個1.jpg是否正常:

Python快速爬取車标網圖檔,以後不要說這什麼車你不認識了!

圖檔下載下傳小技巧

看過了二進制的存儲方式,大家肯定說明白了,網站擷取到圖檔連結然後找着上面的例子下載下傳到本地,然後再進行二進制的讀取後存儲資料庫即可,對嗎?不對…有什麼問題呢?來看一個例子:

Python快速爬取車标網圖檔,以後不要說這什麼車你不認識了!

這裡Audi圖檔的連結位址,我們通過requests來下載下傳看看….

import requests
r =requests.get('http://img.chebiaow.com/thumb/cb/allimg/1303/1-1303061Z600520,c_fill,h_138,w_160.jpg')
r.content
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01...'      

可以看到我們通過requests.get擷取到的content就已經是二進制資料了,為何還要存儲成圖檔,在轉化呢?網頁分析

适配url

針對A-Z的車标排序,網站的url比對關系很簡單:

from string import ascii_uppercase as au
# ascii_uppercase代表A-Z,當然你可以不引入子產品自己生成也OK...
for uppercase in au:
    "http://www.chebiaow.com/logo/{}.html".format(au)      

擷取品牌連結

Python快速爬取車标網圖檔,以後不要說這什麼車你不認識了!

可以看到在包含cb-list方法的ul下比對所有li中的第一個a标簽,然後拼接base_url即可。

品牌詳情

進入品牌詳情界面後,我們針對左右欄目的設定,分别擷取所需标紅的内容

Python快速爬取車标網圖檔,以後不要說這什麼車你不認識了!

整體代碼

通過上面的分析,我們開始爬蟲,但這個網站真的是相應好慢,沒辦法添加上Threading的多線程執行吧,整體代碼如下:

# -*- coding: utf-8 -*-
# @Author   : 王翔
# @JianShu  : 清風Python
# @Date     : 2019/7/22 23:08
# @Software : PyCharm
# @version  :Python 3.7.3
# @File     : CarLogo.py
import os
from db_maker import DbMaker as DB
from string import ascii_uppercase as au
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
from sqlite3 import Binary
import threading
import time
class CarLogo:
    DATABASE = 'car.db'

    def __init__(self):
        self.db = DB()
        self.path = os.path.dirname(os.path.realpath(__file__))
        self.images_path = os.path.join(self.path, 'images_path')
        self.host = "http://www.chebiaow.com"
        self.headers = {
            'Connection': 'keep-alive',
            'user-agent': ('Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 '
                           '(KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36')
        }

    def check_dir(self):
        if not os.path.exists(self.images_path):
            os.mkdir(self.images_path)

    def get_response(self, url, params=None):
        try:
            r = requests.get(url, headers=self.headers, params=params, timeout=15)
        except:
            pass
        soup = BeautifulSoup(r.text, "lxml")
        return soup

    def create_url(self):
        _url_format = "http://www.chebiaow.com/logo/{}.html"
        for uppercase in au:
            try:
                soup = self.get_response(_url_format.format(uppercase))
                _cars = soup.find("ul", {"class": "cb-list"}).findAll('li')
                for car in _cars:
                    # self.car_info()
                    t = threading.Thread(target=self.car_info, args=(urljoin(self.host, car.div.a['href']),))
                    time.sleep(0.5)
                    t.start()
            except:
                pass

    def car_info(self, url):
        soup = self.get_response(url)
        left_index = soup.find("div", {"class": "xq-left"}).findAll('p')
        name = left_index[0].text
        image_byte = requests.get(left_index[1].img['src']).content
        right_index = soup.find("ul", {"class": "xq-right"}).findAll('li')
        founded = right_index[3].span.text
        models = right_index[5].span.text
        website = right_index[7].span.text
        print("Insert Car Logo {}".format(name))
        _sql = "insert into car_logo(name,image,founded,models,website) values (?,?,?,?,?)"
        self.db.insert(_sql, (name, Binary(image_byte), founded, models, website))
if __name__ == '__main__':
    m = CarLogo()
    m.create_url()      

最終存儲的資料庫如下:

Python快速爬取車标網圖檔,以後不要說這什麼車你不認識了!

由于圖檔是BLOB類型的二進制檔案,是以大家看到的是星星,感覺網站的車标是不不夠,怎麼才140多種(雖然我能認識的不到20種…)

這個中興看了半天還以為是搞錯了,沒想到是同名的…

Python快速爬取車标網圖檔,以後不要說這什麼車你不認識了!

OK,今天的内容就到這裡,整理好資料庫,哪天閑了做一個車标的測試題,當然大家可以按照之前我的使用爬蟲+Flask擷取世界國旗資料和孩子一起學習那邊文章引申着自己寫一個車标的練習題。

點選關注,第一時間了解華為雲新鮮技術~