大众点评美食评论爬虫

2023-05-16

 大家都知道的,大众点评用了css反爬,脑壳疼。评论文字使用SVG替换。然后还需要登录才能查看全部评论,也就是要带cookie了,此外时不时跳验证码,验证码还有几种,这帮人是真的过分了,搬砖的何苦为难搬砖的呢。

'''function:从数据库取店铺id取解析店铺下的评论'''
# -*- coding:utf-8 -*-
# Author : peng

from getter import DP2_get   #改成你自己的get方法,怎么处理验证码之类的建议放在这里面
from redis import StrictRedis,ConnectionPool
import threading, time
import re
from pyquery import PyQuery
import os
import json
import random

pool = ConnectionPool(host='localhost', port=***, db=***, password=***)

def word_repair(s,index_dict,svg_dict):
    '''
    s :待替换的字码
    index_dict : 字码坐标字典
    svg_dict: 字库
    '''
    # print(index_dict)
    # print(svg_dict)
    s = re.sub(r'@','',s) #之前添加的用于分割的字符,处理可能存在的残留字符
    try:coordinate = index_dict[s] #字码坐标
    except:
        print('error_______________',s)
        return ''   #错误或者空字符返回空字符
    x = float(coordinate[0]) 
    y = float(coordinate[1])
    '''根据该字码在svg图上的位置解析出该字在svg_dict对应的位置'''
    hight_list = svg_dict.keys()  
    hight_list = [int(_) for _ in svg_dict.keys()]
    if y<hight_list[0]:
        y_key = str(hight_list[0])
    elif y>hight_list[-1]:
        y_key = str(hight_list[-1])
    else:
        for i,n in enumerate(hight_list):
            if n<y<hight_list[i+1]:
                y_key = str(hight_list[i+1])
                break
    x_pos = int(x/14)
    # print(svg_dict)
    word = svg_dict[y_key][x_pos]
    return word

def get_index_dict(html):
    '''
    html:店铺首页的response.text
    '''
    raw = re.findall(r'href="(//s3plus.meituan.net/v1.*?\.css)',html)[0]
    url = 'http:'+raw
    print(url) #css文件链接
    res = DP2_get(url)
    if res == None:
        return None,None
        
    '''解析css文件,解析出字码对应坐标'''
    index_info = re.findall(r'\.(\w+?){background:-(.*?)px\s-(.*?)px;}',res.text)
    index_dict = {}
    for each in index_info:
        index_dict[each[0]]=[each[1],each[2]]

    '''找到主要的svg文件,舍弃次要的svg文件'''
    svgs = re.findall(r'\[class\^="(\S*?)"]{(.*?)(//.*?\.svg)',res.text)
    for each in svgs:
        if 'width: 14px' in each[1] and 'height: 24px' in each[1]:
            svg = each
    svg_url = 'http:'+svg[2]
    svg_name = svg[0]
    
    file_path = 'C:/Users/pengyong/Desktop/DZDP/svg_files/'+svg_name

    '''已经存在则无需更新,不存在则访问下载该svg文件来添加新的svg字典'''
    if not os.path.exists(file_path):
        res2 = DP2_get(svg_url)
        print(res2.url)
        if res2 == None:
            return None,None
        '''svg文件记录,目前发现有两种格式,后一种临时添加,懒得美化代码了'''
        hight_list = re.findall(r'<path id="\d*" d="\w* (\d*?) \w*"/>', res2.text)
        text_list = re.findall(r'<textPath xlink:href="\S*" textLength="\d*">(\S*)</textPath>', res2.text)
        svg_dict = {}
        for i in range(len(hight_list)):
            svg_dict[str(hight_list[i])] = text_list[i]
        if len(svg_dict) == 0:
            #则为第二种格式
            hight_and_text_list = re.findall(r'<text x="\d*" y="(\d*)">(\S*)</text>',res2.text)
            print(hight_and_text_list)
            for i in range(len(hight_and_text_list)):
                svg_dict[str(hight_and_text_list[i][0])] = hight_and_text_list[i][1]

        with open(file_path,'w',encoding='utf-8')as f:
            f.write(str(svg_dict))
    else:
        with open(file_path,'r',encoding='utf-8')as f:
            svg_dict=eval(f.read())
            
    return index_dict,svg_dict

def save(s):
    '''存储评论'''
    with open('DP_comment.txt','a',encoding='utf-8')as f:
        f.write(s+'\n')

def comment_parse(html,index_dict, svg_dict):
    '''
    html: 评论页面
    index_dict: 坐标字典
    svg_dic: 字库
    '''
    divs = re.findall(r'<div class="review-words Hide">(.*?)<div', html, re.S)
    
    def rp(temp):
        '''处理svgmtsi中字码,用#,@做分割标记之类的工作,方便后续处理'''
        svg = temp.group()
        return '#@' + re.findall(r'"(.*?)"', svg)[0] + '#'
        
    for div in divs:
        div = re.sub(r'<svgmtsi class=".*?"></svgmtsi>', rp, div)
        div = re.sub(r'\r', '\n', div)
        div = re.sub(r'<[^<]+?>|\t|\s', '', div)
        words = div.split('#')
        
        for i, word in enumerate(words):
            if word != None and '@' in word:  #判断是否是svgmtsi标签中的字码
                words[i] = word_repair(word, index_dict, svg_dict) #替换
        comment = ''.join(words) #合并
        '''处理评论内容'''
        comment = re.sub(u'&x0A|&x20|&x2F|&x0D', '\n', comment) 
        comment = re.sub(u';', '', comment)
        comment = re.sub(r'^(\s*)\n','',comment)
        print(comment)
        save(comment)

def work():
    redis = StrictRedis(connection_pool=pool)
    while True:
        id = redis.spop('DPids')  # 返回一个元素并删除
        if isinstance(id, bytes):
            id = id.decode()
        # id = '510660'
        url = 'http://www.dianping.com/shop/' + id + '/review_all/p1'
        res = DP2_get(url)

        if res:
            # print(res.text)
            index_dict, svg_dict = get_index_dict(res.text) #获取坐标字典,svg字库
            if index_dict==None or svg_dict == None:
                #获取失败
                break
            comment_parse(res.text, index_dict, svg_dict)
            pages = re.findall(r'<a href="/shop/.*?" data-pg="(\d*?)" class="PageLink"', res.text)
            pages = [int(_) for _ in pages] #类型转换
            try:
                max_page = max(pages)  #最大评论页数
            except:pass
            else:
                if max_page >= 2:
                    for i in range(2, max_page + 1):
                        href = 'http://www.dianping.com/shop/' + id + '/review_all/p' + str(i)
                        print(href)
                        res2 = DP2_get(href)
                        if res2:
                            comment_parse(res2.text, index_dict, svg_dict)
                            n = 15+20*random.random()#平均睡眠25秒
                            time.sleep(n)
        else:
            #记录错误
            with open('error_record.txt', 'a')as f:
                f.write(id)

        
        

if __name__ == '__main__':
    #留着开多线程的,但改成多线程不现实,单线程都休眠25秒了,还得登录,还有封号危险。
    work()
'''function:获取美食店铺id'''

# -*- coding:utf-8 -*-
# Author : peng

from pyquery import PyQuery 
from getter import DP_get
import time
import re
from redis import StrictRedis,ConnectionPool

pool = ConnectionPool(host='localhost', port=***, db=***, password=***)
redis = StrictRedis(connection_pool=pool)

areas = ['beijing','shanghai','guangzhou','shenzhen','tianjin','hangzhou','nanjing','suzhou','chengdu','wuhan','chongqing','xian','tokyo','seoul','bangkok','paris']

id_comp = re.compile(r'"http://www.dianping.com/shop/(\d{4,})" data-click-name')

for area in areas: 
	url = 'http://www.dianping.com/{}/food'.format(area)
	res = DP_get(url)
	if res:
		doc = PyQuery(res.text)
		label_a = doc('#J_nc_cooking > div > ul > li > a')
		for a in label_a.items(): 
			half_url =a.attr('href') 
			# print(a.attr('href'))  /beijing/ch10/g2714
			for i in range(1,51): 
				href2 = 'http://www.dianping.com'+half_url+'p'+str(i)
				GetIdPageRes = DP_get(href2) #分类详情页响应
				if GetIdPageRes:
					shop_ids = re.findall(id_comp,GetIdPageRes.text)
					for each in shop_ids:
						redis.sadd('DPids',each)
						print(each)




				
				


此外,关于大众点评的字体替换,更烦,还好我目前不用搞。

思路是 fontTools解析woff文件,找到编码对应的  ‘笔画’(这个东西吧,看下面)。编码是会变的,就是所谓字体库换了,但这个笔画是不会变的,所以,根据笔画替换编码。至于第一次怎么找到笔画对应什么汉字,我也很脑壳疼。。。。

<TTGlyph name="unieb30" xMin="0" yMin="-101" xMax="935" yMax="827">
      <contour>
        <pt x="447" y="158" on="1"/>
        <pt x="447" y="93" on="1"/>
        <pt x="803" y="93" on="1"/>
        <pt x="803" y="158" on="1"/>
      </contour>
      <contour>
        <pt x="655" y="625" on="1"/>
        <pt x="608" y="596" on="1"/>
        <pt x="669" y="539" on="0"/>
        <pt x="705" y="489" on="1"/>
        <pt x="754" y="524" on="1"/>
        <pt x="720" y="568" on="0"/>
      ........................
      </contour>
      <instructions/>
    </TTGlyph>

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大众点评美食评论爬虫 的相关文章

随机推荐

  • 【Fluent】XYplot中导出随着XYZ单一坐标变化的物理量规律

    一 问题背景 之前我写的博客里 xff0c 讲了如何导出区域内所有节点 单元格中心的XYZ三坐标 xff0c 及其这个节点 单元格中心上存储的物理量信息 但是有时候 xff0c 我们有一个需求 只需要X Y Z坐标中的一个 例如我们需要导出
  • 【Ansys】mechanical和fluent求解器中使用的迭代方法-待补充

    一 mechanical求解器 这个求解器 xff0c 在网上很容易查到 xff0c 迭代求解时用的就是牛顿 拉夫逊方法 xff08 Newton Raphson xff09 这是因为牛顿法求解非线性问题非常优秀 而mechanical使用
  • UART(通用异步收发传输器)

    1 UART其在数据发送时将并行数据转换成串行数据来传输 xff0c 在数据接收时将接收到的 串行数据转换成并行数据 是异步串行通信的总称 2 而 RS232 RS449 RS423 RS422 和 RS485 等是对应各种异步串行通信口的
  • C++——迭代器Iterator

    Iterator简介 迭代器是一个抽象的概念 xff0c 其可以说是算法与容器之间的桥梁 xff0c 迭代器提供一种方法 xff0c 使之能够依存巡防某个聚合物 xff08 容器 xff09 所含的所有元素 xff0c 而有无需暴露该聚合物
  • ubuntu下开发can数据的接收和发送案例(开发实战一)

    ubuntu下开发can数据的接收和发送案例 一 linux下通用can收发模块说明 二 参数配置 三 代码示例 四 需要安装的包和参考学习 一 linux下通用can收发模块说明 Linux具有通用的can库 可以用来开发can数据收发
  • CAN原理讲解,以及NVIDIA的tx2接收can消息,并进行can设置(开发实战二)

    CAN原理讲解 以及NVIDIA的tx2接收can消息 并进行can设置 A 接线原理图以及引脚定义 B NVIDIA的tx2接收can 并进行can设置 C can原理讲解 以及注意事项 A 接线原理图以及引脚定义 引脚定义配置和查看的学
  • ULN2003步进电机 5V/12V步进电机 28BYJ-48步进电机 13003驱动板开发者文档

    13003步进电机驱动板介绍 我们设计的13003驱动板在核心电路上做了优化 xff0c 如果驱动板电源不小心接反了一下 xff0c 不会击穿单片机 可以驱动5v 28BYJ 48步进电机 12v28BYJ 48步进电机 单片机本身的io可
  • 记录一次ros的rviz和gazebo仿真地图,以及slam建模出现闪烁的问题,以及原因分析,机器人小车配置问题

    记录一次ros的rviz和gazebo仿真地图地图出现闪烁的问题 xff0c 以及原因分析 URDF 43 Gazebo 43 Rviz仿真 看到建立的地图是乱的 xff0c 原因是我的小车配置文件controllers xff0c 也就是
  • 蓝牙通信、串口通信、和can通信以及MCU之间的关系

    说明 xff1a 其端口和can需要设置波特率 xff1a 250 500 xff0c 和can的类型 xff0c can1 can2 串口直接和模拟量通信需要设置串口的信息 xff0c 如下图 xff1a 蓝牙和模拟量通信 xff0c 不
  • 使用 IDEA 几分钟就重构了同事800 行"又臭又长" 的类!真香!

    Python实战社群 Java实战社群 长按识别下方二维码 xff0c 按需求添加 扫码关注添加客服 进Python社群 扫码关注添加客服 进Java社群 来源丨java思维导图 http suo im 6fsMvG 最近在对已有项目进行扩
  • 全面了解超声波传感器

    为了研究和利用超声波 xff0c 人们已经设计和制成了许多超声波发生器 总体上讲 xff0c 超声波发生器可以分为两大类 xff1a 一类是用电气方式产生超声波 xff0c 一类是用机械方式产生超声波 电气方式包括压电型 磁致伸缩型和电动型
  • 卡尔曼滤波---公式推导和一些疑问

    该笔记是在学习up主DR CAN的关于卡尔曼滤波视频后做的笔记整理 up主主页 xff1a https space bilibili com 230105574 文章中有三个链接 xff0c 补充如下 xff1a 贝叶斯滤波 为什么是两个高
  • 联想笔记本G50-80 bios白名单修改

    联想笔记本G50 80 bios白名单修改 缘由 xff1a 更换网卡为AX200 xff0c 遇到bios白名单的限制 xff0c 需要修改bios程序 bios型号 xff1a B0CNA0WW 软件工具 xff1a UEFITOOL
  • acwing笔记

    文章目录 基础知识快速排序归并排序二分查找 基础数据结构数组模拟单链表trie字符串统计并查集堆模板 搜索和图论邻接表数组实现dfsbfskmp最短路最小生成树二分图 数学知识动态规划dp背包问题 贪心 基础知识 快速排序 span cla
  • 20220323华为笔试

    1 span class token macro property span class token directive hash span span class token directive keyword include span s
  • 《葵花宝典》计算机网络篇幅

    文章目录 七层网络模型和五层网络模型 xff0c 以及各自都有哪些常见协议 xff1f TCP UDP对比 xff0c 使用选择TCP为什么可靠 UDP怎样才能可靠扩展考察点 xff1a QUIC 协议TCP UDP报文头部格式TCP三次握
  • 亚马逊爬虫-python

    找实习遇到的作业 xff1a 最终结果 xff1a 实现代码分两部分 xff1a 抓取书籍id 爬取详细数据 1 xff1a import requests import re from pyquery import PyQuery as
  • http请求转串口通信模块实现网页发送文字硬件语音播放(esp8266 串口语音模块 )

    首先你有这样的8266 这两种8266自身带2个按键和烧录芯片方便调试 xff0c 综合性价比较高 还有就是需要这样的串口语音播放模块 有了这些我们开始吧 xff01 1 先看一段视频效果演示 xff0c 再来介绍实现步骤 http请求转串
  • 多智能体系统编队算法仿真--python3实现

    初始条件 xff1a 智能体位置随机生成所有智能体位置全局可知目标多边形位置给定所有个体运行相同算法 xff0c 根据环境来决定自己动作 目标 xff1a 形成均匀多边形分布 xff0c 所谓的 均匀 效果如下图 xff1a 即是多边形上间
  • 大众点评美食评论爬虫

    大家都知道的 xff0c 大众点评用了css反爬 xff0c 脑壳疼 评论文字使用SVG替换 然后还需要登录才能查看全部评论 xff0c 也就是要带cookie了 xff0c 此外时不时跳验证码 xff0c 验证码还有几种 xff0c 这帮