使用python创建爬虫非常简单: Meituan.com数据采集技能,如果您有基础,就开始爬网!

优采云 发布时间: 2020-08-08 14:49

  1. 数据采集工具简介

  如今,大多数动态网站通过浏览器端的js发起ajax请求,然后在接收到数据后呈现页面. 在这种情况下,采集数据,通过脚本启动http获取请求以及在获取DOM文档页面之后解析和提取有用数据的方法是不可行的. 然后有人会想到通过F12打开浏览器控制台来分析服务器api,然后模拟请求相应的api以获取我们想要的数据. 这个想法在某些情况下是可行的,但是许多大型网站都会采用一些防爬网策略,出于安全考虑,通常会在界面中添加安全验证. 例如,在请求页面之前,只能请求相关的标头和cookie. 有些还限制了请求的来源,等等,这一次通过这种方式采集数据就更加困难了. 我们还有其他有效的方法吗?当然,python爬虫非常简单,让我们首先了解Selenium和Selectors,然后通过抓取美团在线业务信息的示例总结一些数据采集技术:

  2. 页面抓取数据分析和数据表创建

  以朝阳大悦城的一家美食餐厅为数据采集示例,该网站为:

  https://www.meituan.com/meishi/40453459/

  2.1获取数据

  我们要捕获的数据的第一部分是企业的基本信息,包括企业名称,地址,电话号码和营业时间. 在分析了多个美食企业之后,我们知道这些企业的Web界面在布局上基本相同. 因此我们的采集器可以编写更通用的内容. 为了防止重复抓取业务数据,我们还将业务的URL信息存储在数据表中.

  

  第二部分要捕获的数据是美食餐厅的招牌菜. 每个商店基本上都有自己的特色菜. 我们还将保存这些数据并将其存储在另一个数据表中.

  

  我们要捕获的数据的最后一部分是用户评论. 这部分数据对我们来说非常有价值. 将来,我们可以分析这部分数据以提取有关业务的更多信息. 我们要获取的信息的这一部分包括: 评论者的昵称,星级,评论内容,评论时间,如果有图片,我们还需要以列表的形式保存图片的地址.

  

  2.2创建数据表

  我们用来存储数据的数据库是Mysql,Python有一个相关的ORM,我们在项目中使用了peewee. 但是,建议在创建数据表时使用本机SQL,以便我们可以灵活地控制字段属性,设置引擎和字符编码格式等. 使用Python的ORM也可以实现结果,但是ORM是数据库层的封装,例如sqlite,sqlserver数据库和Mysql,仍然存在一些差异,使用ORM只能使用这些数据库的公共部分. 以下是存储数据所需的数据表sql:

  CREATE TABLE `merchant` ( #商家表

`id` int(11) NOT NULL AUTO_INCREMENT,

`name` varchar(255) NOT NULL COMMENT '商家名称',

`address` varchar(255) NOT NULL COMMENT '地址',

`website_address` varchar(255) NOT NULL COMMENT '网址',

`website_address_hash` varchar(32) NOT NULL COMMENT '网址hash',

`mobile` varchar(32) NOT NULL COMMENT '电话',

`business_hours` varchar(255) NOT NULL COMMENT '营业时间',

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;

CREATE TABLE `recommended_dish` ( #推荐菜表

`id` int(11) NOT NULL AUTO_INCREMENT,

`merchant_id` int(11) NOT NULL COMMENT '商家id',

`name` varchar(255) NOT NULL COMMENT '推荐菜名称',

PRIMARY KEY (`id`),

KEY `recommended_dish_merchant_id` (`merchant_id`),

CONSTRAINT `recommended_dish_ibfk_1` FOREIGN KEY (`merchant_id`) REFERENCES `merchant` (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=309 DEFAULT CHARSET=utf8mb4;

CREATE TABLE `evaluate` ( #评论表

`id` int(11) NOT NULL AUTO_INCREMENT,

`merchant_id` int(11) NOT NULL COMMENT '商家id',

`user_name` varchar(255) DEFAULT '' COMMENT '评论人昵称',

`evaluate_time` datetime NOT NULL COMMENT '评论时间',

`content` varchar(10000) DEFAULT '' COMMENT '评论内容',

`star` tinyint(4) DEFAULT '0' COMMENT '星级',

`image_list` varchar(1000) DEFAULT '' COMMENT '图片列表',

PRIMARY KEY (`id`),

KEY `evaluate_merchant_id` (`merchant_id`),

CONSTRAINT `evaluate_ibfk_1` FOREIGN KEY (`merchant_id`) REFERENCES `merchant` (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=8427 DEFAULT CHARSET=utf8mb4;

  相应地,我们还可以使用Python的ORM创建管理数据表. 稍后在分析代码时,我们将讨论peewee在mysql数据库上的一些常见操作,例如查询数据,插入数据库数据和返回id. 批量插入数据库等,读者可以采集相关材料并进行系统学习.

  meituan_spider / models.py代码:

  from peewee import *

# 连接数据库

db = MySQLDatabase("meituan_spider", host="127.0.0.1", port=3306, user="root", password="root", charset="utf8")

class BaseModel(Model):

class Meta:

database = db

# 商家表,用来存放商家信息

class Merchant(BaseModel):

id = AutoField(primary_key=True, verbose_name="商家id")

name = CharField(max_length=255, verbose_name="商家名称")

address = CharField(max_length=255, verbose_name="商家地址")

website_address = CharField(max_length=255, verbose_name="网络地址")

website_address_hash = CharField(max_length=32, verbose_name="网络地址的md5值,为了快速索引")

mobile = CharField(max_length=32, verbose_name="商家电话")

business_hours = CharField(max_length=255, verbose_name="营业时间")

# 商家推荐菜表,存放菜品的推荐信息

class Recommended_dish(BaseModel):

merchant_id = ForeignKeyField(Merchant, verbose_name="商家外键")

name = CharField(max_length=255, verbose_name="推荐菜名称")

# 用户评价表,存放用户的评论信息

class Evaluate(BaseModel):

id = CharField(primary_key=True)

merchant_id = ForeignKeyField(Merchant, verbose_name="商家外键")

user_name = CharField(verbose_name="用户名")

evaluate_time = DateTimeField(verbose_name="评价时间")

content = TextField(default="", verbose_name="评论内容")

star = IntegerField(default=0, verbose_name="评分")

image_list = TextField(default="", verbose_name="图片")

if __name__ == "__main__":

db.create_tables([Merchant, Recommended_dish, Evaluate])

  3. 代码实现和详细说明

  代码相对简单,但是要运行代码,您需要安装上述工具包: 还需要安装硒,scrapy和peewee,这些软件包可以通过pip来安装;另外,还需要安装selenium驱动程序浏览器相应的驱动程序,因为我在本地使用chrome浏览器,所以我下载了相关版本的chromedriver,将在以后使用. 要求读者检查使用python操作硒所需的准备工作,并手动设置相关环境. 接下来,详细分析代码;源代码如下:

<p>from selenium import webdriver

from selenium.webdriver.chrome.options import Options

from selenium.common.exceptions import NoSuchElementException

from scrapy import Selector

from models import *

import hashlib

import os

import re

import time

import json

chrome_options = Options()

# 设置headless模式,这种方式下无启动界面,能够加速程序的运行

# chrome_options.add_argument("--headless")

# 禁用gpu防止渲染图片

chrome_options.add_argument(&#39;disable-gpu&#39;)

# 设置不加载图片

chrome_options.add_argument(&#39;blink-settings=imagesEnabled=false&#39;)

# 通过页面展示的像素数计算星级

def star_num(num):

numbers = {

"16.8": 1,

"33.6": 2,

"50.4": 3,

"67.2": 4,

"84": 5

}

return numbers.get(num, 0)

# 解析商家内容

def parse(merchant_id):

weblink = "https://www.meituan.com/meishi/{}/".format(merchant_id)

# 启动selenium

browser = webdriver.Chrome(executable_path="/Users/guozhaoran/python/tools/chromedriver", options=chrome_options)

browser.get(weblink)

# 不重复爬取数据

hash_weblink = hashlib.md5(weblink.encode(encoding=&#39;utf-8&#39;)).hexdigest()

existed = Merchant.select().where(Merchant.website_address_hash == hash_weblink)

if (existed):

print("数据已经爬取")

os._exit(0)

time.sleep(2)

# print(browser.page_source) #获取到网页渲染后的内容

sel = Selector(text=browser.page_source)

# 提取商家的基本信息

# 商家名称

name = "".join(sel.xpath("//div[@id=&#39;app&#39;]//div[@class=&#39;d-left&#39;]//div[@class=&#39;name&#39;]/text()").extract()).strip()

detail = sel.xpath("//div[@id=&#39;app&#39;]//div[@class=&#39;d-left&#39;]//div[@class=&#39;address&#39;]//p/text()").extract()

address = "".join(detail[1].strip())

mobile = "".join(detail[3].strip())

business_hours = "".join(detail[5].strip())

# 保存商家信息

merchant_id = Merchant.insert(name=name, address=address, website_address=weblink,

website_address_hash=hash_weblink, mobile=mobile, business_hours=business_hours

).execute()

# 获取推荐菜信息

recommended_dish_list = sel.xpath(

"//div[@id=&#39;app&#39;]//div[@class=&#39;recommend&#39;]//div[@class=&#39;list clear&#39;]//span/text()").extract()

# 遍历获取到的数据,批量插入数据库

dish_data = [{

&#39;merchant_id&#39;: merchant_id,

&#39;name&#39;: i

} for i in recommended_dish_list]

Recommended_dish.insert_many(dish_data).execute()

# 也可以遍历list,一条条插入数据库

# for dish in recommended_dish_list:

# Recommended_dish.create(merchant_id=merchant_id, name=dish)

# 查看链接一共有多少页的评论

page_num = 0

try:

page_num = sel.xpath(

"//div[@id=&#39;app&#39;]//div[@class=&#39;mt-pagination&#39;]//ul[@class=&#39;pagination clear&#39;]//li[last()-1]//span/text()").extract_first()

page_num = int("".join(page_num).strip())

# page_num = int(page_num)

except NoSuchElementException as e:

print("改商家没有用户评论信息")

os._exit(0)

# 当有用户评论数据,每页每页的读取用户数据

if (page_num):

i = 1

number_pattern = re.compile(r"\d+\.?\d*")

chinese_pattern = re.compile(u"[\u4e00-\u9fa5]+")

illegal_str = re.compile(u&#39;[^0-9a-zA-Z\u4e00-\u9fa5.,,。?“”]+&#39;, re.UNICODE)

while (i

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线