查看原文
其他

网络爬虫 | 批量采集话题「如何评价淄博烧烤?」的回答

大邓 大邓和他的Python
2024-09-09

一、采集数据

最近淄博烧烤一直很火,岁数大了,莫名其妙就被有人情味的短视频感动。我从小在山东长大,一直25岁离开山东。我记得09年升大学前后,我记得山东宣传的口号「好客山东,欢迎您」,但是一直在生活在山东, 对好客的理解不够深刻。后来走过的地方多了,对比之下才知道「好客山东」 不仅仅是口号,更是山东人民好客的真实写照。淄博烧烤的出圈,不是口味,也不是价格,是淄博乃至山东仁义价值观的成功。

知乎话题「如何评价淄博的烧烤?」数据采集于2023年5月12日。之前分享过付费代码, 网络爬虫(付费)  |  知乎热门话题「全职儿女」  ,现在免费公开数据采集部分代码。公众号内的代码复制容易出问题, 建议textdata.cn中找本文对应的博文,准确复制代码。

根据截图,获取爬虫运行的初始参数

#话题ID 
question_id = 510779192

#话题回答数 
reply_num = 1178

https://www.zhihu.com/question/510779192

import csv
import requests
import time


#知乎话题ID
question_id = '510779192'
#当前回答数
reply_num = 1178


#存储csv,文件名为话题ID
with open(f'{question_id}.csv''w', encoding='utf-8', newline=''as csvf:
    #字段
    fieldnames = ['name''userID''gender''headline'
                  'is_advertiser''is_org''utype''can_comment',
                 'follower_count''content''updated_time''voteup_count']
    writer = csv.DictWriter(csvf, fieldnames=fieldnames)
    writer.writeheader()
    
    #网址规律
    url = f'https://www.zhihu.com/api/v4/questions/{question_id}/feeds'
    next_url = ''
    data = {
        'include''data[*].is_normal,admin_closed_comment,reward_info,is_collapsed,annotation_action,annotation_detail,collapse_reason,is_sticky,collapsed_by,suggest_edit,comment_count,can_comment,content,editable_content,attachment,voteup_count,reshipment_settings,comment_permission,created_time,updated_time,review_info,relevant_info,question,excerpt,is_labeled,paid_info,paid_info_content,reaction_instruction,relationship.is_authorized,is_author,voting,is_thanked,is_nothelp,is_recognized;data[*].mark_infos[*].url;data[*].author.follower_count,vip_info,badge[*].topics;data[*].settings.table_of_content.enabled',
        'offset'0,
        'limit'5,
        'order''updated'}
    headers = {'user-agent''Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'}

    #循环抓取
    max_page = int(reply_num/5)+1
    for page in range(1, max_page+1):
        time.sleep(1)
        #发起访问
        if next_url:
            resp = requests.get(next_url, headers=headers)
        else:
            resp = requests.get(url, params=data, headers=headers)
        answers = resp.json().get('data')
        for answer in answers:
            #构造数据,写入csv
            linedata = {
                'name': answer['target']['author']['name'],
                'userID': answer['target']['author']['id'],
                'gender': answer['target']['author']['gender'],
                'headline': answer['target']['author']['headline'],
                'is_advertiser':  answer['target']['author']['is_advertiser'],
                'is_org': answer['target']['author']['is_org'],
                'utype': answer['target']['author']['type'],
                'can_comment': answer['target']['can_comment']['status'],
                'follower_count': answer['target']['author']['follower_count'],
                'content': answer['target']['excerpt'], 
                'updated_time': answer['target']['updated_time'],
                'voteup_count': answer['target']['voteup_count']
            }
            writer.writerow(linedata)
            print(page, linedata)
            cursor = answer['cursor']
        next_url = resp.json()['paging']['next']

Run

1 {'name''喝冬瓜''userID''f1f53bb38926323a746cf5e178c1700e''gender': 1, 'headline''粉红''is_advertiser': False, 'is_org': False, 'utype''people''can_comment': True, 'follower_count': 1165, 'content''好吃 便宜实惠 还能吃饱 真不赚钱''updated_time': 1683883047, 'voteup_count': 0}
1 {'name''阿楠''userID''30bac2de00cb2f738f6eae4d9f10caca''gender': -1, 'headline''''is_advertiser': False, 'is_org': False, 'utype''people''can_comment': True, 'follower_count': 12, 'content''淄博出牌:旅游不宰客 全国其他城市:要不起''updated_time': 1683883035, 'voteup_count': 0}
1 {'name''孤独的独''userID''88a9bd770972c1e26dd111c37163c026''gender': 1, 'headline''独而不孤的行者''is_advertiser': False, 'is_org': False, 'utype''people''can_comment': True, 'follower_count': 55, 'content''我敲,题主有故事啊,不管你们营销什么的,也有可能是营销号随手捡的一个问题。只有我留意到这个一年前的细节了吗? [图片]''updated_time': 1683877105, 'voteup_count': 0}
1 {'name''coral''userID''6d5fd85d3a13ba997883e3618bd99c3c''gender': 0, 'headline''永远年轻,永远说话难听。''is_advertiser': False, 'is_org': False, 'utype''people''can_comment': True, 'follower_count': 1, 'content''【淄博烧烤爆火 自然因素】 ①地理位置优越,地处鲁中地区,与各地距离适中; ②临近胶州半岛沿海城市,海鲜产量大种类多; ③临近寿光蔬菜种植基地,菜多且优惠; ④山东是农业大省、养殖大省,肉类多且实惠,面食品类多; ⑤铁矿煤矿是淄博支柱产业,烧烤所需煤炭等资源丰富。 【淄博烧烤爆火 社会经济因素】 ①交通便利,火车高铁出行便捷,设立多条烧烤专线; ②政策支持,设多条旅游专线,打造文化特色产业; ③品牌效应显…''updated_time': 1683874251, 'voteup_count': 0}
......
231 {'name''刘朗''userID''9910b16a1a160f78eb3145b17ea6c2d7''gender': -1, 'headline''习惯穷追猛打,但凡发现别人挑衅我不回复都是被人拉黑了''is_advertiser': False, 'is_org': False, 'utype''people''can_comment': True, 'follower_count': 1275, 'content''那我给你说一下我自己吃淄博临淄烧烤怎么吃的行不? 第一步点菜,淄博烧烤是论把!也就是剔出铁钎后纯肉的重量,现在的一把也是一斤的意思,有些店还是说一斤多少钱,一斤在二十来串左右,那像我临淄不是回民的,我要是俩人去吃,就跟老板说两把带皮五花,十块钱的鱼豆腐,十块钱的板筋,然后我会看看有啥烤的蔬菜,毕竟我还是注重点荤素搭配的,但是只要五块钱的蔬菜,我今年吃的最后一顿烧烤是要了五块钱的烤甘蓝,然后就是点…''updated_time': 1643545237, 'voteup_count': 414}
231 {'name''牛儿还在山坡吃草''userID''ea9769e15a5b82be698c04c99229685c''gender': 1, 'headline''「不接受反驳」的人,就不应该在公共平台发表观点,不是吗?''is_advertiser': False, 'is_org': False, 'utype''people''can_comment': True, 'follower_count': 70, 'content''淄博烧烤特别出名,淄博烧烤配有小饼和大葱,先用葱沾一下甜面酱,然后拿两串烧烤撸到饼里,然后撒上芝麻盐,花生碎用小饼一卷,咬一口,就会感觉人间值得。 淄博烧烤是每个淄博人都喜欢吃的美食,曾经在外地读大学的我也经常想念这一味道,吃来吃去每次吃烧烤胖两斤但是仍然抵制不了烧烤的诱惑,吃烧烤在别人眼里显得非常奇怪,但是在淄博人眼中,不吃烧烤才奇怪! 淄博走两步都是烧烤店,淄博烧烤遍布在淄博的大街小巷,几天不…''updated_time': 1641866413, 'voteup_count': 11}
231 {'name''王屋与太行''userID''64d7364c4811186497e8d68e61af8f91''gender': 0, 'headline''在人群里唱自己的歌''is_advertiser': False, 'is_org': False, 'utype''people''can_comment': True, 'follower_count': 7, 'content''听说过,没吃过,用饼卷?''updated_time': 1641789783, 'voteup_count': 0}
232 {'name''哆咪喵''userID''768248562c2d0c295092b56c0e5b75d4''gender': 0, 'headline''注册安全工程师、危化行业EHS十年,敬业认真学习能力强''is_advertiser': False, 'is_org': False, 'utype''people''can_comment': True, 'follower_count': 136, 'content''淄博烧烤独成一派,好吃,几乎每月都有两三次烧烤家庭式聚餐,你值得拥有,如果味道能稍微淡一点就更好了''updated_time': 1641787110, 'voteup_count': 3}



二、读取数据

读取刚刚采集的 1156 条回答数据,存储于  510779192.csv

回答数据字段含

  • name  用户(知乎回答者)名
  • userID 用户ID
  • gender 用户性别, 1为男性, 0为女性, -1未知。
  • headline 用户签名
  • is_advertiser 用户是否为广告人员
  • is_org 用户是否为机构
  • utype 用户的类型
  • follower_count 用户的粉丝数
  • content 回答的内容
  • can_comment 其他用户是否有权限对该回答进行互动评论
  • updated_time 更新时间,时间戳。
  • voteup_count 点赞数
import pandas as pd

df = pd.read_csv('510779192.csv', encoding='utf-8')
df.head()


#1178条数据,采集到1156条
len(df)

Run

1156



三、探索性分析

数据存储为csv,可以借助pandas做一些简单的统计性分析。

3.1 性别

df.describe()


#该话题男性占比
#男1, 女0, 未知-1。
male = len(df[df.gender==1])/len(df)
female = len(df[df.gender==0])/len(df)
other_sex = len(df[df.gender==-1])/len(df)

print(f'男性占比 : {male}')
print(f'女性占比 : {female}')
print(f'未知占比 : {other_sex}')

Run

男性占比 : 0.509515570934256
女性占比 : 0.157439446366782
未知占比 : 0.33304498269896193

3.2 用户身份

  • 回答者账号是机构号
  • 回答者账号是营销者
df.is_org.value_counts()

Run

    False    1144
    True       12
    Name: is_org, dtype: int64

#回答者账号是机构的占比
df.is_org.sum()/len(df)

Run

    0.010380622837370242

#回答者账号是机构的
df[df.is_org==True][['name''headline''content''voteup_count']]

3.3 时间

采集的时间数据类似1682334790,是一种时间戳记录方式。

时间戳是某时间距 1970 年 1 月 1 日 00:00:00 UTC 所经过的秒数。

df['updated_time']

Run

0 1683883047
1 1683883035
2 1683877105
3 1683874251
4 1683872223
...
1151 1664872959
1152 1643545237
1153 1641866413
1154 1641789783
1155 1641787110
Name: updated_time, Length: 1156, dtype: int64

import datetime
df['updated_time'] = df['updated_time'].apply(lambda k: datetime.datetime.fromtimestamp(k))
df['updated_time']

Run

0 2023-05-12 17:17:27
1 2023-05-12 17:17:15
2 2023-05-12 15:38:25
3 2023-05-12 14:50:51
4 2023-05-12 14:17:03
...
1151 2022-10-04 16:42:39
1152 2022-01-30 20:20:37
1153 2022-01-11 10:00:13
1154 2022-01-10 12:43:03
1155 2022-01-10 11:58:30
Name: updated_time, Length: 1156, dtype: datetime64[ns]

查看下这些知乎用户回答的24小时分布情况

import matplotlib.pyplot as plt
import matplotlib
import matplotlib_inline
matplotlib_inline.backend_inline.set_matplotlib_formats('png''svg')
import scienceplots
import platform
plt.style.use(['science''no-latex''cjk-sc-font'])
system = platform.system()  # 获取操作系统类型

if system == 'Windows':
    font = {'family''SimHei'}
elif system == 'Darwin':
    font = {'family''Arial Unicode MS'}
else:
    font = {'family''sans-serif'}
matplotlib.rc('font', **font)  # 设置全局字体

plt.figure(figsize=(128))

df['updated_time'].dt.hour.value_counts(normalize=True).sort_index().plot(kind='bar')
plt.title('话题「如何评价淄博的烧烤?」的回答时间分布', fontsize=20)
plt.xlabel('小时', fontsize=18)
plt.ylabel('占比', rotation=0, fontsize=18)

3.3 词云图

运行词云图代码,查看该话题回答的概览。

df.content

Run

0 好吃 便宜实惠 还能吃饱 真不赚钱
1 淄博出牌:旅游不宰客 全国其他城市:要不起
2 我敲,题主有故事啊,不管你们营销什么的,也有可能是营销号随手捡的一个问题。只有我留意到这个一...
3 【淄博烧烤爆火 自然因素】 ①地理位置优越,地处鲁中地区,与各地距离适中;②临近胶州半岛沿...
4 火起来是因为济南的大学生去 为啥济南的大学生要坐高铁去吃烧烤 因为tmd十年前济南烧烤进屋了...
...
1151 前段时间,抖音大V乌拉拉来临淄吃烧烤,让淄博又刷了波热度,与有荣焉的同时,伴随着内讧不止,诸...
1152 那我给你说一下我自己吃淄博临淄烧烤怎么吃的行不?第一步点菜,淄博烧烤是论把!也就是剔出铁钎...
1153 淄博烧烤特别出名,淄博烧烤配有小饼和大葱,先用葱沾一下甜面酱,然后拿两串烧烤撸到饼里,然后撒...
1154 听说过,没吃过,用饼卷?
1155 淄博烧烤独成一派,好吃,几乎每月都有两三次烧烤家庭式聚餐,你值得拥有,如果味道能稍微淡一点就更好了
Name: content, Length: 1156, dtype: object

import jieba
from pyecharts import options as opts
from pyecharts.charts import WordCloud
import re

#text = ''.join(df.content.tolist())
text = ''.join(str(item) for item in df.content.tolist() if not isinstance(item, float))

text = re.sub('[^\u4e00-\u9fa5]+''', text)
words = jieba.lcut(text)
words = [w for w in words if len(w)>1]

records = []
for w in set(words):
    freq = words.count(w)
    records.append((w, freq))
    

records = sorted(records, key=lambda k:k[1], reverse=True)
wordcounts = [(w, str(f)) for w,f in records]

wc = WordCloud()
wc.add(series_name="", data_pair=wordcounts, word_size_range=[20100])
wc.set_global_opts(
        title_opts=opts.TitleOpts(title="「淄博烧烤」词云图", title_textstyle_opts=opts.TextStyleOpts(font_size=23)
        ),
        tooltip_opts=opts.TooltipOpts(is_show=True),
    )
    


wc.render("淄博烧烤.html")  #存储位置

Run

    Building prefix dict from the default dictionary ...
    Loading model from cache /var/folders/y0/4gqxky0s2t94x1c1qhlwr6100000gn/T/jieba.cache
    Loading model cost 0.457 seconds.
    Prefix dict has been built successfully.
    '/Users/deng/Desktop/2023-05-12-welcome-to-zibo-barbecue/淄博烧烤.html'

生成的 淄博烧烤.html 文件850kb,使用浏览器打开时候如果看不到内容,不要慌,需要渲染大概30秒才能出图


精选内容

管理世界 | 使用文本分析词构建并测量 短视主义

管理世界 | 使用 经营讨论与分析 测量 企业数字化指标

管理世界 | 用正则表达式、文本向量化、线性回归算法从md&a数据中计算 「企业融资约束指标

管理世界 | 政府与市场心理因素的经济影响及其测度

文本分析 | 中国企业高管团队创新注意力(含代码)

金融研究 | 使用Python构建「关键审计事项信息含量」

PNAS | 14000+篇心理学顶刊论文可复现性调研(含代码)

网络爬虫 | 使用Python采集B站弹幕和评论数据

网络爬虫 | 使用Python披露采集 Up 主视频详情信息

B站 | "高铁互殴"视频词云图绘制

可视化 | 绘制《三体》人物关系网络图

可视化 | 99-21年地方政府报告关键词变化趋势

使用 Word2Vec 和 TF-IDF 计算五类企业文化

采购合同数据集 | 政府采购何以牵动企业创新

96G数据集 | 2亿条中国大陆企业工商注册信息

70G数据集 | 3571万条专利申请数据集(1985-2022年)

93G数据集 | 中国裁判文书网(2010~2021)

数据集 | 3.9G全国POI地点兴趣点数据集

数据集 | 「问询函」

数据集 | 07-21年上市公司「委托贷款公告」

单个csv文件体积大于电脑内存,怎么办?

继续滑动看下一个
大邓和他的Python
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存