【爬虫成长之路】(六)【大众点评】mitmproxy中间人代理爬虫

本系列文章共十篇:

【爬虫成长之路】(一)爬虫系列文章导读
【爬虫成长之路】(二)各篇需要用到的库和工具
【爬虫成长之路】(三)【大众点评】selenium爬虫
【爬虫成长之路】(四)【大众点评】selenium登录+requests爬取数据
【爬虫成长之路】(五)【大众点评】浏览器扫码登录+油猴直接爬取数据
【爬虫成长之路】(六)【大众点评】mitmproxy中间人代理爬虫
【爬虫成长之路】(七)【大众点评】PC微信小程序+requests爬取数据
【爬虫成长之路】(八)【大众点评】安卓APP爬虫

本文需要用到的工具:mitmproxy中间人代理
本文需要用到的库:mitmproxybs4

爬取目标数据:

  1. 指定城市的店铺列表及其评分数据
  2. 指定店铺下的用户评论数据

一、需求分析

这一篇总共需要爬取两个页面的数据,分别是:

  1. 某城市的店铺列表页面
  2. 某店铺的评论列表页面

二、获取目标页面的URL

这里与前面获取的URL一致,不需要进行修改:

# 进行URL匹配时需要适当修改匹配规则
http://www.dianping.com/guangzhou/ch10
http://www.dianping.com/shop/H7fXoNAkaf******/review_all

三、mitmproxy简介和使用

mitmproxy是一款HTTP/HTTPS代理工具,其功能类似于Fiddler、Postman、Charles等抓包软件,不同之处在于mitmproxy提供了更为高级的开发接口,通过使用这些接口,我们能轻易的获取到HTTP数据,并对其进行修改。
mitmproxy官网地址

使用mitmproxy有几个地方需要注意,官网文档有详细说明,我在这里简单说一下大概使用步骤:

  1. mitmproxy 软件安装(需要安装mitmproxy软件才能使用)
  2. 安装mitmproxy的python库,pip install mitmproxy
  3. 阅读文档,编写程序
  4. 命令行启动mitmproxy,指定端口写好的程序(windows下是mitmdump,Linux下是mitmdump,还有一个图形界面mitmweb)
  5. 修改本地代理端口和命令行启动时配置的端口一致(如果还有其他代理软件开着,建议先关闭,避免相互影响)
  6. 安装mitmproxy的证书,证书下载地址是mitm.it,详细安装可参考官网关于证书

如果mitmproxy安装有问题的,可以参考如下文章:

  1. mitmproxy的安装
  2. Python3+mitmproxy安装使用教程(Windows)
  3. 安装mitmproxy以及遇到的坑和简单用法

四、分析文档结构

这里和前面的第三篇、第四篇都是一致的,稍作修改即可,所以就不再重复了。

五、编写程序

其实关于mitmproxy获取数据的部分很简单,主要是要知道mitmproxy的工作原理,关键代码只需要按固定的格式去编写就好了。

程序启动方式
在控制台输入命令:

mitmdump -p 8000 -q -s mitm_spider.py
序号 参数 说明
1 -p 指定代理端口,这里需要和系统中配置的一致,否则代理不起作用,之后记得改回来
2 -q 可以屏蔽掉默认的无关输出
3 -s 指定脚本程序所在的路径

这里主要就是匹配URL,匹配到URL之后,就可以使用flow.response.text获取响应的内容了,之后便是和前面文章介绍的一样按固定格式提取数据即可。

关键代码:

import mitmproxy
from mitmproxy import ctx,http
from mitmproxy.http import flow

class Spider:
    def response(self, flow:flow):
        # 去掉cookie的HttpOnly参数
        shop_list_url = 'http://www.dianping.com/guangzhou'

        url = flow.request.url
        if url.startswith(shop_list_url):
            print(f'mitm 劫持成功,URL= {url}')
            body = flow.response.text
            #shop_info = parse_shop(body)
        elif 'review_all' in url and url.startswith('http://www.dianping.com'):
            print(f'mitm 劫持成功,URL= {url}')
            body = flow.response.text
            #comment_list = parse_comment(body)

addons = [
    Spider(),
]

全部程序源码:

import mitmproxy
import traceback
from mitmproxy import ctx,http
from mitmproxy.http import flow
from bs4 import BeautifulSoup as BS


def parse_shop(html):
    shop_info = []
    soup = BS(html, 'lxml')
    page_shop = soup.find_all('div', class_='txt')
    for shop in page_shop:
        shop_info.append({
            'shopid': shop.a['data-shopid'],
            'name': shop.a.text.strip(),
            'score': shop.find('div', class_='nebula_star').text.strip()
        })
    return shop_info


def parse_comment(html):
    soup = BS(html, 'lxml')
    comments = soup.find_all('div', class_='main-review')
    comment_list = []
    for item in comments:   # 遍历所有评论
        username = item.find('div', class_='dper-info').text.strip()
        items = item.find_all('span', class_='item')     # 各项评分
        detail_score = []
        for _item in items:
            detail_score.append(_item.text.strip())
        content = item.find('div', class_='review-words').text.strip()  # 获取到的评论不全,做了CSS加密
        comment_list.append({'username': username, 'item': detail_score, 'content': content})
    return comment_list


class Spider:
    def response(self, flow:flow):
        # 去掉cookie的HttpOnly参数
        shop_list_url = 'http://www.dianping.com/guangzhou'

        url = flow.request.url
        if url.startswith(shop_list_url):
            print(f'mitm 劫持成功,URL= {url}')
            # headers = flow.request.headers
            body = flow.response.text
            shop_info = parse_shop(body)
            for _ in shop_info:
                print(_)
        elif 'review_all' in url and url.startswith('http://www.dianping.com'):
            print(f'mitm 劫持成功,URL= {url}')
            # headers = flow.request.headers
            body = flow.response.text
            comment_list = parse_comment(body)
            for _ in comment_list:
                print(_)
                print(20*'--')


addons = [
    Spider(),
]

六、程序运行结果

程序运行结果如下,如果需要进一步处理,或需要提取更多的字段,可以重新编写数据解析函数。

mitmproxy劫取结果

七、优缺点分析

序号 优点 缺点
1 程序编写简单 可能会遇到部分APP反代理,检测到使用代理后直接不工作
2 几乎没有反爬问题,不用构造参数 配置过程稍微有点繁琐

第三~六篇所使用的爬取方法都没有参数构造问题,所以在很多场合下,如果对爬取速度要求不高的话,这几种方法是很好的。在做爬虫的过程中,很大部分的精力基本上是放在找接口参数构造上面的,这几篇文章所用到的方法中,接口容易查找,也不用构造参数,所以还是很有意义的。但是对于想要进一步提高爬取速度,这些方法都是不能满足要求的。

接下来的文章当中会讲解如何适当的提高爬取速度。其实对现在的爬虫来说,并不能一味的提高爬取速度,稳定其实相对来说显得更为重要些,如果在爬取过程中出现验证码,这也是一个麻烦的事,验证码大量出现的时候,是很容易被封账号的。

注:

  1. 如果您不希望我在文章提及您文章的链接,或是对您的服务器造成了损害,请联系我对文章进行修改;
  2. 本文仅爬取公开数据,不涉及到用户隐私;

你可能感兴趣的:(【爬虫成长之路】(六)【大众点评】mitmproxy中间人代理爬虫)