爬取美团

实战 Python 网络爬虫:美团美食商家信息和用户评论

1、网站分析及项目设计

美食是人类的毕生追求,说到美食,咱们总会想起美团美食,面对类型众多的商家,应如何选择优质的商家,使消费最大合理化。在本 Chat 里,将讲述如何爬取美团商家信息。正则表达式

废话很少说,咱们直接在浏览器打开美团美食的网址,而后打开谷歌的开发者工具,并刷新网页,从新捕捉请求资源,如图所示:sql

根据店名在 Network 选项卡的各个分类标签下查找数据所在的 HTML 源码位置,在每一个请求信息的 Response 下使用 Ctrl+F 快速查找店名(初漾台味黑糖),最终在 Doc 标签下找到相关信息,如图所示:数据库

从图上的信息能够看到,地址栏的 gz 表明区域“广州”,全国的美食商家是以城市进行划分的。而商家的数据是以 JSON 格式表示,网页上显示的信息均可以在此找到。在这个网页中,咱们是要查找这个商家的 URL 地址,从而进入商家详细页。浏览器

但从美团美食的首页中,咱们能获取的信息就这么多,所以,咱们先访问店家详细页,发现商家详细页的 URL 地址带有一串数字。不一样的商家,数字内容都不同,如图所示:markdown

经过对比发现,每一个商家详细页的 URL 地址只有末端的数字串是不相同的,这应该是美团给商家标记的 id,咱们取其中一个商家 id 回到美团首页查找,发现可找到相关信息,如图所示:网络

根据上述分析,咱们能够在美团美食首页里获取商家 id,经过 id 来构建商家详细页的 URL 地址。框架

获得了商家详细页的 URL 地址后,下一步是在商家详细页里进行数据爬取。数据爬取分为两部分:商家信息和顾客评论,如图所示:函数

首先,咱们找出商家信息所在的请求信息,在开发者工具的 Network 选项卡的 doc 标签下找到相关信息,商家信息是在 doc 标签下找到,而且也是以 JSON 格式表示,如图所示:工具

接着是分析顾客评论所在的请求信息,最终在 XHR 标签下找到相关的请求信息,如图所示:网站

综合上述,咱们须要从三个请求信息里获取数据,三个请求信息的说明以下:

  • 美团美食的首页地址,获取每一个商家的 id
  • 商家详细页地址,获取商家信息
  • 顾客评论的 AJAX 接口,获取顾客评论信息

目前只是简单分析了三个请求信息,每一个请求的请求参数和请求头会在功能实现的过程当中详细讲解。

根据现有的分析,咱们建立项目文件夹 meituan,项目文件分别有 Insql.py、meishi.conf 和 meishi.py,文件说明以下:

  • Insql.py 是将数据入库处理,由 ORM 框架 SQLAlchemy 实现
  • meishi.conf 设置区域信息,如广州(gz)或北京(bj)等,从而控制爬虫的爬取方向
  • meishi.py 实现爬虫功能

 

2、爬取全部商家信息

简单分析网页后,接下来咱们先实现全部商家的信息爬取。因为商家详细页只须要商家 id 便可,所以爬取全部商家信息只需爬取商家 id 便可。

从美团美食的首页得知,其 URL 地址的“gz”表明广州。首页的底部设有分页功能,当点击第二页的时候,URL 末端新增下级目录 pn2,第三页的下级目录为 pn3,以此类推,新增的下级目录表明分页的页数。当遍历 32 次便可获得当前城市全部美食商家信息,如图所示:

根据 URL 的变化规律和商家信息的 HTML 源码结构,全部商家信息的爬取功能定义为函数 get_all(),函数参数 city_list 表明各个城市信息并以字符串表示,如 gz、bj 等,函数代码如图所示:

函数 get_all() 所实现的功能说明以下:

  • 首先将参数 city_list 以英文逗号进行截取,获得各个城市的拼音缩写。
  • 而后遍历各个城市,分别爬取各个城市的美食信息,每一个城市只显示 32 页的美食信息,所以须要遍历 32 次。
  • 每次遍历都会对当前分页发送 HTTP 请求,请求头设有 Upgrade-Insecure-Requests、Host 和 Referer 属性,这些属性最好写入请求头,这样能够避开反爬虫检测。特别是 Host 属性,由于 URL 的域名设有城市信息,如 gz.meituan.com,而 Host 属性是为 URL 指定相应的域名,使其一一对应。
  • 从当前请求中获取响应内容,并用正则表达式提取当前分页全部的商家 id(即find_poiId)以及访客信息 find_uuid。
  • 调用函数 get_info(),将爬取的数据做为函数参数传入。函数 get_info() 是进入商家详细页,爬取商家的基本信息。

 

3、分别爬取每一个商家的信息和用户评论信息

在函数 get_all() 里,咱们调用了函数 get_info(),它是进入访问商家详细页的,主要爬取商家的基本信息。商家详情页的 URL 地址为 http://www.meituan.com/meishi/%s/,其中 %s 表明商家 id。

注意:若是对商家详细页发送 HTTP 请求,这里涉及了一个反爬虫机制——Cookies 的使用,咱们查看该请求的请求头内容。如图所示:

商家详细页的请求头与通常的请求头并没有太大差别,按照以往的开发模式,首先构架 URL 地址,而后对 URL 发送请求,最后从请求里获取响应内容并提取目标数据。按照该思路,商家的基本信息爬取功能如图所示:

当运行程序的时候,程序是没有提取到商家信息了,这说明该请求的响应内容不是商家详细页的网页内容,确定遇到反爬虫检测。在请求头里,除了还没有加入 Cookies 以外,其他属性已添加,所以,咱们尝试加入 Cookies,发现能够提取到商家信息。

可是只使用一个 Cookies 也会中断爬取过程,缘由在于访问频繁。为了下降访问频繁,引入 Cookies 池,将代码的请求部分进行修改,以下所示:

从函数 get_info() 里可到,它调用了函数 get_comment(),并将商家 ID 和 find_uuid 分别传入,find_uuid 是从函数 get_all()提取出来的数据,这两个函数参数都是构建顾客评论的 AJAX 接口的请求参数,如图所示:

  • 请求参数 uuid 是函数参数 find_uuid
  • 请求参数 originUrl 是商家详细页的 URL 地址
  • 请求参数 id 是商家 id

所以,函数 get_comment() 的代码如图所示:

 

4、ORM 框架实现数据持久化存储

爬虫的核心功能大体已实现,接着讲解数据存储方面。数据存储以 MySQL 为例,存储过程使用 ORM 框架 SQLAlchemy,这样可实现数据持久化,它的优势此处不一一讲述。

首先在 Insql.py 里导入 ORM 框架 SQLAlchemy,并建立相关对象,经过 SQLAlchemy 链接本地 MySQL 数据库。数据库编码设为 UTF8mb4,由于评论信息里可能出现手机表情这类特殊内容,这些特殊内容是超出 UTF-8 的编码范围。代码以下:

将商家信息和顾客评论信息分别存储在数据表 meituan_shop 和 meituan_comment。数据表之间存在一对多的数据关系,一个商家会有多条顾客评论,映射类的定义以下:

上述只是定义映射类,数据存储的功能还没有实现。数据存储由函数 shop_db() 和函数 comment_db() 实现,二者会对待存储的数据进行判断,若是数据已存在数据库,则进行更新处理,反之新增一条数据。代码以下:

 

5、设置配置文件,动态控制爬取方向

配置文件给爬虫程序 meishi.py 读取,用于控制爬虫的爬取方向,好比爬取北京、上海等城市的美食信息。将配置文件命名为 meishi.conf,配置信息以下:

配置文件只设置配置属性 city,属性值是将每一个城市编号以英文逗号的形式拼接起来,城市编号是首个字母拼音开头组成的。函数 get_all() 的函数参数 city_list 就是配置属性 city。

在爬虫文件 meishi.py 里,文件运行函数 _main_ 主要读取配置文件的配置属性 city,并调用函数 get_all(),代码以下:

 
 
 
 
 
 
本内容转自:帅b大佬的博客