本系列文章共十篇:
【爬虫成长之路】(一)爬虫系列文章导读
【爬虫成长之路】(二)各篇需要用到的库和工具
【爬虫成长之路】(三)【大众点评】selenium爬虫
【爬虫成长之路】(四)【大众点评】selenium登录+requests爬取数据
【爬虫成长之路】(五)【大众点评】浏览器扫码登录+油猴直接爬取数据
【爬虫成长之路】(六)【大众点评】mitmproxy中间人代理爬虫
【爬虫成长之路】(七)【大众点评】PC微信小程序+requests爬取数据
【爬虫成长之路】(八)【大众点评】安卓APP爬虫
本文需要用到的工具:
mitmproxy
中间人代理
本文需要用到的库:mitmproxy
、bs4
爬取目标数据:
- 指定城市的店铺列表及其评分数据
- 指定店铺下的用户评论数据
一、需求分析
这一篇总共需要爬取两个页面的数据,分别是:
- 某城市的
店铺列表
页面 - 某店铺的
评论列表
页面
二、获取目标页面的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有几个地方需要注意,官网文档有详细说明,我在这里简单说一下大概使用步骤:
- mitmproxy 软件安装(需要安装mitmproxy软件才能使用)
- 安装mitmproxy的python库,
pip install mitmproxy
- 阅读文档,编写程序
- 命令行启动mitmproxy,指定
端口
和写好的程序
(windows下是mitmdump,Linux下是mitmdump,还有一个图形界面mitmweb)- 修改本地代理端口和命令行启动时配置的端口一致(如果还有其他代理软件开着,建议先关闭,避免相互影响)
- 安装mitmproxy的证书,证书下载地址是mitm.it,详细安装可参考官网关于证书
如果mitmproxy安装有问题的,可以参考如下文章:
- mitmproxy的安装
- Python3+mitmproxy安装使用教程(Windows)
- 安装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(),
]
六、程序运行结果
程序运行结果如下,如果需要进一步处理,或需要提取更多的字段,可以重新编写数据解析函数。
七、优缺点分析
序号 | 优点 | 缺点 |
---|---|---|
1 | 程序编写简单 | 可能会遇到部分APP反代理,检测到使用代理后直接不工作 |
2 | 几乎没有反爬问题,不用构造参数 | 配置过程稍微有点繁琐 |
第三~六篇所使用的爬取方法都没有参数构造问题,所以在很多场合下,如果对爬取速度要求不高的话,这几种方法是很好的。在做爬虫的过程中,很大部分的精力基本上是放在找接口
和参数构造
上面的,这几篇文章所用到的方法中,接口容易查找,也不用构造参数,所以还是很有意义的。但是对于想要进一步提高爬取速度,这些方法都是不能满足要求的。
接下来的文章当中会讲解如何适当的提高爬取速度。其实对现在的爬虫来说,并不能一味的提高爬取速度,稳定其实相对来说显得更为重要些,如果在爬取过程中出现验证码,这也是一个麻烦的事,验证码大量出现的时候,是很容易被封账号的。
注:
- 如果您不希望我在文章提及您文章的链接,或是对您的服务器造成了损害,请联系我对文章进行修改;
- 本文仅爬取公开数据,不涉及到用户隐私;