猫哥教你写爬虫 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

相关文章
相关标签/搜索