貓哥教你寫爬蟲 046--協程-實踐-吃什麼不會胖

吃什麼不會胖?

低熱量食物

食物的數量有千千萬,若是咱們要爬取食物熱量的話,這個數據量必然很大。

使用多協程來爬取大量的數據是很是合理且明智的選擇

1559543546800

若是咱們要爬取的話,那就得選定一個有存儲食物熱量信息的網站才能爬到數據

薄荷網。它是一個跟健身減肥有關,且能夠查詢食物數據的網站

1559543609537

www.boohee.com/food/

任務: 用多協程爬取薄荷網的食物熱量信息

簡單瀏覽一下這個網站,你會發現一共有11個常見食物分類

1559543702863

點擊【谷薯芋、雜豆、主食】這個分類,你會看到在食物分類的右邊,有10頁食物的記錄,包含了這個分類裏食物的名字,及其熱量信息。點擊食物的名字還會跳轉到食物的詳情頁面。

1559543746295

咱們能夠從爬蟲四步(獲取數據→解析數據→提取數據→存儲數據)入手,開始逐一分析

1559543840537

咱們須要建立數據庫

mysql> create database boohee character set utf8;
Query OK, 1 row affected (0.00 sec)
mysql> use boohee;
Database changed
mysql> create table food(id int primary key auto_increment, category varchar(20) not null, name varchar(200) not null, calorie varchar(200) not null);
Query OK, 0 rows affected (0.03 sec)
mysql> desc food;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| category | varchar(20)  | NO   |     | NULL    |                |
| name     | varchar(200) | NO   |     | NULL    |                |
| calorie  | varchar(200) | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+
4 rows in set (0.02 sec)
複製代碼

1559543999252

www.boohee.com/food/group/…

1表明第一個分類, page=1表明第一頁

1559544241097
1559544267952
1559544288707

咱們先來一個正常的版本, 按順序執行的那種...

每一個分類, 爬取三頁, 看統計一下時間...

import requests
from bs4 import BeautifulSoup
import pymysql
import time
connection = pymysql.connect(user='root', password='root', db='boohee')
cursor = connection.cursor()
category_list = []
def create_table():
    cursor.execute('drop database boohee')
    cursor.execute('create database boohee character set utf8')
    cursor.execute('use boohee')
    cursor.execute(
        'create table food(id int primary key auto_increment, category varchar(20) not null, name varchar(200) not null, calorie varchar(200) not null)')
    connection.commit()
def get_category():
    soup = BeautifulSoup(requests.get(
        'http://www.boohee.com/food/').text, 'html.parser')
    li_tag_list = soup.find_all(
        'li', class_='col-md-4 col-sm-4 col-xs-12 item')
    for li_tag in li_tag_list:
        category_list.append(li_tag.find(
            'div', class_='text-box').find('a').text)
def get_food():
    for index, cate in enumerate(category_list):
        if index != 11:
            for i in range(1, 3):
                url = "http://www.boohee.com/food/group/{}?page={}".format(
                    index+1, i)
                soup = BeautifulSoup(requests.get(url).text, 'html.parser')
                for div_tag in soup.find_all('div', class_="text-box pull-left"):
                    category = cate
                    name = div_tag.find('a')['title']
                    calorie = div_tag.find('p').text[3:]
                    add_food(category, name, calorie)
        else:
            for i in range(1, 3):
                url = 'http://www.boohee.com/food/view_menu?page={}'.format(i)
                soup = BeautifulSoup(requests.get(url).text, 'html.parser')
                for div_tag in soup.find_all('div', class_="text-box pull-left"):
                    category = cate
                    name = div_tag.find('a')['title']
                    calorie = div_tag.find('p').text[3:]
                    add_food(category, name, calorie)
def add_food(category, name, calorie):
    sql = "insert into food(category,name,calorie) values({},{},{})".format(
        repr(category), repr(name), repr(calorie))
    print(sql)
    cursor.execute(sql)
    connection.commit()
if __name__ == "__main__":
    start = time.time()
    create_table()
    get_category()
    get_food()
    print(time.time() - start)
複製代碼

看看運行效果...

C:\Users\Administrator\Desktop\demo>python -u "c:\Users\Administrator\Desktop\demo\just_test.py"
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','Easy Fun 紫薯養分粥','317 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','白粥(粳米),又叫稀飯,大米粥,白米粥,米粥,大米湯','46 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','白粥(秈米),又叫稀飯,大米粥,白米粥','59 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','玉米(鮮),又叫苞谷、珍珠米、棒子、玉蜀黍、苞米、六穀','112 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','燕麥片,又叫燕麥','338 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','麪條(生),又叫面','301 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','麪條(煮),又叫面','110 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','秈米粉,又叫米線、米粉、粉','356 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','麪包','313 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','紅薯,又叫地瓜、番薯、甘薯','90 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','小米粥','46 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','馬鈴薯,又叫土豆、洋芋、地蛋、山藥蛋、洋番薯','81 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','包子(豬肉餡)','227 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','米飯,又叫大米飯,飯,蒸米','116 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','白薯,又叫山芋、紅皮山芋,地瓜、甘薯','106 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','大米,又叫稻米、米、生米','346 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','全麥麪包,又叫全麥麪包、全麥吐司、全麥麪包片','246 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','烙餅','259 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','花捲','214 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','油條','388 大卡(每100克)')
insert into food(category,name,calorie) values('谷薯芋、雜豆、主食','嘉頓 生命麪包 450g','284 大卡(每100克)')
......
insert into food(category,name,calorie) values('菜餚','扒鮮蘆筍','86 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','果汁豬扒','173 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','蝦仁扒油菜','61 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','蒜蓉玉叩雞胗','129 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','蔬菜扒素腸','90 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','鳳尾菇扒蛋','100 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','扒蝴蝶蝦','168 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','鐵扒巴德好司牛排','144 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','德州五香脫骨扒雞','168 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','扒素腸','116 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','白菜扒豬肝','54 大卡(每100克)')
insert into food(category,name,calorie) values('菜餚','蠔油芥藍素肉絲','128 大卡(每100克)')
7.019520282745361
複製代碼

差很少用來7秒...

咱們看一下數據庫...

1559701676133

代碼是沒有問題的, 剩下的就是看看協程怎麼寫...

from gevent import monkey
monkey.patch_all()
# 導入所需的庫和模塊:
import pymysql
import csv
import bs4
import requests
import gevent
from gevent.queue import Queue
sql_list = []
# 建立隊列對象,並賦值給work。
work = Queue()
# 前3個常見食物分類的前3頁的食物記錄的網址:
url_1 = 'http://www.boohee.com/food/group/{type}?page={page}'
# 經過兩個for循環,能設置分類的數字和頁數的數字。
for x in range(1, 11):
    for y in range(1, 11):
        real_url = url_1.format(type=x, page=y)
        # 而後,把構造好的網址用put_nowait添加進隊列裏。
        work.put_nowait(real_url)
# 第11個常見食物分類的前3頁的食物記錄的網址:
url_2 = 'http://www.boohee.com/food/view_menu?page={page}'
# 經過for循環,能設置第11個常見食物分類的食物的頁數。
for x in range(1, 11):
    real_url = url_2.format(page=x)
    # 而後,把構造好的網址用put_nowait添加進隊
    work.put_nowait(real_url)
# 定義crawler函數
def crawler():
    # 添加請求頭
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
    }
    # 當隊列不是空的時候,就執行下面的程序。
    while not work.empty():
        # 用get_nowait()方法從隊列裏把剛剛放入的網址提取出來。
        url = work.get_nowait()
        # 用requests.get獲取網頁源代碼。
        res = requests.get(url, headers=headers)
        # 用BeautifulSoup解析網頁源代碼。
        bs_res = bs4.BeautifulSoup(res.text, 'html.parser')
        # 獲取當前分類
        category = bs_res.find('div',class_="widget-food-list pull-right").find('h3').text
        # 用find_all提取出<li class="item clearfix">標籤的內容。
        foods = bs_res.find_all('li', class_='item clearfix')
        # 遍歷foods
        for food in foods:
            # 用find_all在<li class="item clearfix">標籤下,提取出第2個<a>元素title屬性的值,也就是食物名稱。
            food_name = food.find_all('a')[1]['title']
            # 用find在<li class="item clearfix">標籤下,提取<p>元素,再用text方法留下純文本,就提取出了食物的熱量。
            food_calorie = food.find('p').text[3:]
            # 打印食物的名稱。
            sql = "insert into food(category,name,calorie) values({},{},{})".format(repr(category), repr(food_name), repr(food_calorie))
            sql_list.append(sql)
# 建立空的任務列表
tasks_list = []
# 至關於建立了5個爬蟲
for x in range(5):
    # 用gevent.spawn()函數建立執行crawler()函數的任務。
    task = gevent.spawn(crawler)
    # 往任務列表添加任務。
    tasks_list.append(task)
# 用gevent.joinall方法,啓動協程,執行任務列表裏的全部任務,讓爬蟲開始爬取網站。
gevent.joinall(tasks_list)
connection = pymysql.connect(user='root', password='root', db='boohee')
cursor = connection.cursor()
cursor.execute('drop database boohee')
cursor.execute('create database boohee character set utf8')
cursor.execute('use boohee')
cursor.execute('create table food(id int primary key auto_increment, category varchar(20) not null, name varchar(200) not null, calorie varchar(200) not null)')
connection.commit()
for sql in sql_list:
    cursor.execute(sql)
    connection.commit()
connection.close()
複製代碼

1559726980787
1559727107435
1559727131054

快速跳轉:

貓哥教你寫爬蟲 000--開篇.md
貓哥教你寫爬蟲 001--print()函數和變量.md
貓哥教你寫爬蟲 002--做業-打印皮卡丘.md
貓哥教你寫爬蟲 003--數據類型轉換.md
貓哥教你寫爬蟲 004--數據類型轉換-小練習.md
貓哥教你寫爬蟲 005--數據類型轉換-小做業.md
貓哥教你寫爬蟲 006--條件判斷和條件嵌套.md
貓哥教你寫爬蟲 007--條件判斷和條件嵌套-小做業.md
貓哥教你寫爬蟲 008--input()函數.md
貓哥教你寫爬蟲 009--input()函數-人工智能小愛同窗.md
貓哥教你寫爬蟲 010--列表,字典,循環.md
貓哥教你寫爬蟲 011--列表,字典,循環-小做業.md
貓哥教你寫爬蟲 012--布爾值和四種語句.md
貓哥教你寫爬蟲 013--布爾值和四種語句-小做業.md
貓哥教你寫爬蟲 014--pk小遊戲.md
貓哥教你寫爬蟲 015--pk小遊戲(全新改版).md
貓哥教你寫爬蟲 016--函數.md
貓哥教你寫爬蟲 017--函數-小做業.md
貓哥教你寫爬蟲 018--debug.md
貓哥教你寫爬蟲 019--debug-做業.md
貓哥教你寫爬蟲 020--類與對象(上).md
貓哥教你寫爬蟲 021--類與對象(上)-做業.md
貓哥教你寫爬蟲 022--類與對象(下).md
貓哥教你寫爬蟲 023--類與對象(下)-做業.md
貓哥教你寫爬蟲 024--編碼&&解碼.md
貓哥教你寫爬蟲 025--編碼&&解碼-小做業.md
貓哥教你寫爬蟲 026--模塊.md
貓哥教你寫爬蟲 027--模塊介紹.md
貓哥教你寫爬蟲 028--模塊介紹-小做業-廣告牌.md
貓哥教你寫爬蟲 029--爬蟲初探-requests.md
貓哥教你寫爬蟲 030--爬蟲初探-requests-做業.md
貓哥教你寫爬蟲 031--爬蟲基礎-html.md
貓哥教你寫爬蟲 032--爬蟲初體驗-BeautifulSoup.md
貓哥教你寫爬蟲 033--爬蟲初體驗-BeautifulSoup-做業.md
貓哥教你寫爬蟲 034--爬蟲-BeautifulSoup實踐.md
貓哥教你寫爬蟲 035--爬蟲-BeautifulSoup實踐-做業-電影top250.md
貓哥教你寫爬蟲 036--爬蟲-BeautifulSoup實踐-做業-電影top250-做業解析.md
貓哥教你寫爬蟲 037--爬蟲-寶寶要聽歌.md
貓哥教你寫爬蟲 038--帶參數請求.md
貓哥教你寫爬蟲 039--存儲數據.md
貓哥教你寫爬蟲 040--存儲數據-做業.md
貓哥教你寫爬蟲 041--模擬登陸-cookie.md
貓哥教你寫爬蟲 042--session的用法.md
貓哥教你寫爬蟲 043--模擬瀏覽器.md
貓哥教你寫爬蟲 044--模擬瀏覽器-做業.md
貓哥教你寫爬蟲 045--協程.md
貓哥教你寫爬蟲 046--協程-實踐-吃什麼不會胖.md
貓哥教你寫爬蟲 047--scrapy框架.md
貓哥教你寫爬蟲 048--爬蟲和反爬蟲.md
貓哥教你寫爬蟲 049--完結撒花.mdhtml

相關文章
相關標籤/搜索