分享Python爬虫代码,获取抖音和微博热搜信息
以下是一个简单的Python爬虫代码,用于爬取头条、抖音和微博热搜: ```python import requests from bs4 import BeautifulSoup def get_hot_search(): url = "https://www.toutiao.com/" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"} response = requests.get(url, headers=headers) soup = BeautifulSoup(response.text, 'html.parser') hot_search = soup.find('div', class_='hot-search-list').find_all('a') for
总功能如下
自动化分类;整体匹配率:81%~94%左右;其中,微博噪音最大,失真较高,信息价值相对较低。
情感分析;每条文本情感值与整体平均值。(见最后透视图)
基础热度分析;指数平均值与总值,从指数推测三者平台用户总量占有情况。
语法分析;主要针对副词、数词、形容词、限定词,标记出可能存在引导情绪、话题讨论的词语
词频统计;如果一个热搜条目在三者信息平台都有出现,说明可能为持续性的话题热度,其信息密度较高。
Python代码
pip 环境
pipinstallbs4pipinstalljiebapipinstallopenpyxlpipinstallrequestspipinstalljsonpipinstallsnownlppipinstallurllibpipinstallstanza
lite
python-c"$(curl-fsSLhttps://ghproxy.com/https://raw.githubusercontent.com/hoochanlon/ihs-simple/main/d-python/get_resou_today.py)"
full
python-c"$(curl-fsSLhttps://ghproxy.com/https://raw.githubusercontent.com/hoochanlon/ihs-simple/main/d-python/get_resou_today_s.py)"
爬虫代码:
importosfromdatetimeimportdatetimeimportopenpyxlimportrequestsfrombs4importBeautifulSoupfromopenpyxlimportWorkbookfromsnownlpimportSnowNLPimportjiebafromcollectionsimportCounterimportjieba.possegaspsegimportjsonimporturllib.requestimportstanza#确定保存文本格式用的。defget_save_path_xlsx_file():"""获取格式化后的当前时间:return:格式化后的当前时间字符串"""#进行跨平台处理保存路径returnos.path.join(os.path.join(os.path.expanduser("~"),"Desktop"),"resoubang_{}.xlsx".format(datetime.now().strftime('%Y-%m-%d')))#解析新闻函数defget_news_from_url(url:str):"""从指定的URL抓取热搜新闻:paramurl:网页URL:return:热搜新闻列表"""headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36''(KHTML,likeGecko)Chrome/58.0.3029.110Safari/537.3'}r=requests.get(url,headers=headers)r.encoding='utf-8'soup=BeautifulSoup(r.text,'html.parser')toutiao_resoubang=soup.find_all('div',class_='single-entrytindent')resoubang_list=[]foritemintoutiao_resoubang:spans=item.find_all('span')forspaninspans:resoubang_list.append(span.string)returnresoubang_list#删除空行defdelete_empty_rows(sheet_name:str,wb:Workbook):"""删除指定工作表中的空行:paramsheet_name:工作表名称:paramwb:Excel工作簿对象:paramNone关键字https://notes-by-yangjinjie.readthedocs.io/zh_CN/latest/python/05-modules/openpyxl.html?highlight=openpyxl"""ws=wb[sheet_name]#迭代行所用的内置函数ws.iter_rows()forrowinws.iter_rows():ifall(cell.valueisNoneforcellinrow):ws.delete_rows(row[0].row)#计数平均指数、情感得分defcalculate_average_index_and_sentiment_score(sheet_name:str,wb:Workbook):"""计算指定工作表中热搜新闻的平均指数和情感得分:paramsheet_name:工作表名称:paramwb:Excel工作簿对象:return:平均指数、情感得分元组"""ws=wb[sheet_name]total_index=0count=0sentiment_score_list=[]forrowinws.iter_rows(min_row=2,min_col=1,max_col=3):news_str=''forcellinrow:ifcell.valueisnotNone:news_str+=str(cell.value)#功能挺多,见:https://github.com/isnowfy/snownlps=SnowNLP(news_str)sentiment_score=s.sentimentssentiment_score_list.append(sentiment_score)#row[2]是指每一行中的第三个单元格,也就是第三列。total_index+=row[2].valuecount+=1ws.cell(row=row[0].row,column=4,value=sentiment_score)#每张表的平均指数与情感得分return(total_index/count,sum(sentiment_score_list)/len(sentiment_score_list))#统计词频defcalculate_word_count(sheet_names:list,wb:Workbook):"""计算工作表中出现最多的20个单词,将结果写入新的工作表中:paramsheet_names:工作表名称:paramwb:Excel工作簿对象:paramstopwords_file:停用词文件路径停用词是指在自然语言中使用频率很高,但通常不具有实际含义或对文本分析任务没有太大帮助的单词,如“的”,“了”等。"""#停用词文件stopwords_file='https://ghproxy.com/https://raw.githubusercontent.com/goto456/stopwords/master/cn_stopwords.txt'#请求停用词库response=requests.get(stopwords_file)stopwords=response.content.decode('utf-8').split('\n')#加载停用词库forwordinstopwords:jieba.del_word(word.strip())#遍历所有工作表,统计词频,由于语料库词汇功能欠佳,只能粗略统计word_count=Counter()forsheet_nameinsheet_names:ws=wb[sheet_name]forrowinws.iter_rows(min_row=2,min_col=1,max_col=3):news_str=''forcellinrow:ifcell.valueisnotNone:news_str+=str(cell.value)words=jieba.lcut(news_str)#只要是数值类型的忽略。#words=[wordforwordinwordsifnot(word.isdigit()or(word.replace('w','').replace('.','').isdigit()))]new_words=[]forwordinwords:#忽略长度为0或1的字符串iflen(word)<=1:continue#去除数值噪声ifnot(word.isdigit()or(word.replace('w','').replace('.','').isdigit())):new_words.append(word)words=new_words#更新词库集word_count.update(words)#去掉停用词forwordinlist(word_count):ifwordinstopwords:delword_count[word]#取出出现最多的30个词top_words=word_count.most_common(30)#创建一个新的工作表ws=wb.create_sheet(title='词频统计')#添加行ws.append(['排名','词语','词频'])#从1开始计数,而非0开始排名fori,(word,freq)inenumerate(top_words,1):ws.append([i,word,freq])#2023.5.9新增分类功能defwrite_category_to_sheet(sheet_name:str,wb:Workbook):"""将新闻事件的关键词分类信息写入到Excel工作表中的第五列中:paramsheet_name:工作表名称:paramwb:Excel工作簿对象:jieba分词:https://github.com/fxsjy/jieba"""#调用在线分类字典json#从URL获取JSON数据response=urllib.request.urlopen('https://ghproxy.com/https://raw.githubusercontent.com/hoochanlon/ihs-simple/main/AQUICK/category_news.json')json_data=response.read().decode('utf-8')#解析JSON数据category_keywords=json.loads(json_data)#从当前sheet开始ws=wb[sheet_name]forrowinws.iter_rows(min_row=2,min_col=1,max_col=4):title_str=''forcellinrow:ifcell.valueisnotNone:title_str+=str(cell.value)#将标题字符串分词并转换为列表数组words=pseg.cut(title_str)category=''forword,flaginwords:#内置的字符串方法,用于检查前缀指定开头#ifflag.startswith('n'):#keykeywords关键字,.items()检索键值对forkey,keywordsincategory_keywords.items():ifwordinkeywords:category=keybreakifcategory:breakifnotcategory:category='其他'ws.cell(row=row[0].row,column=5,value=category)#将已解析网页排版的数据,按规则写入到xlsx,行列对称,条理分明。defwrite_news_to_sheet(news_list:list,sheet_name:str,wb:Workbook):"""将新闻列表写入到Excel工作表中:paramnews_list:新闻列表:paramsheet_name:工作表名称:paramwb:Excel工作簿对象:cell.value.isnumeric()表示当前字符串是否能表示为一个数字:isinstance(cell.value,str)表示当前值是否字符串"""ws=wb.create_sheet(title=sheet_name)row=[]fori,iteminenumerate(news_list,start=1):ifi>=156:#抽取50组数据(如果索引大于156是关于微博的其他介绍文章)continueifi%3==1:##索引从0开始,即2%3,往后是新组数据。item=item.replace("、","")row.append(item)ifi%3==0:#取模被整除,3列一组,被整除说明已到3列,换行。ws.append(row)row=[]#从第二行开始迭代每一行数据forrowinws.iter_rows(min_row=2,min_col=1):forcellinrow:ifcell.column==1orcell.column==3:#实例判断,如果是返回True,否则返回False。ifisinstance(cell.value,str)andnotcell.value.isnumeric():#去除字符串中的'[置顶]'字符,185为2、3、4排名的平均值(实时)cell.value=cell.value.replace('[置顶]','185w')ifisinstance(cell.value,str)andcell.value.isnumeric():cell.value=int(cell.value)elifisinstance(cell.value,str):cell.value=float(cell.value.replace('w',''))ws.cell(row=1,column=3,value='指数(万)')ws.cell(row=1,column=4,value='情感得分')ws.cell(row=1,column=5,value='分类')#处理整合,爬取各50条热搜,并计算文本情感值、自动化分类、词频统计deffenmenbielei():result_list=[]#定义一个空列表,用于存储每个表格的平均指数和情感得分urls=['http://resou.today/art/11.html','http://resou.today/art/22.html','http://resou.today/art/6.html']sheet_names=['今日头条热榜','抖音时事热榜','微博热搜']wb=Workbook()#wb.remove(wb['Sheet'])forurl,sheet_nameinzip(urls,sheet_names):news_list=get_news_from_url(url)#写入网页解析的数据到xlsxwrite_news_to_sheet(news_list,sheet_name,wb)#删除操作留下的空行delete_empty_rows(sheet_name,wb)#分类write_category_to_sheet(sheet_name,wb)#统计平均指数、各表平均情感值average_index,sentiment_score=calculate_average_index_and_sentiment_score(sheet_name,wb)#print(f'{sheet_name}平均指数:{average_index:.2f}情感得分:{sentiment_score:.2f}')result_list.append((average_index,sentiment_score))#将平均指数和情感得分以元组的形式添加到result_list中#词频统计calculate_word_count(sheet_names,wb)#删除空表,并保存为指定文件wb.remove(wb['Sheet']);wb.save(get_save_path_xlsx_file())returnresult_list#5.13新增:xlsx新闻热搜词性分析defadd_special_pos_columns(sheet):'''赠加文本词性识别stanza:https://stanfordnlp.github.io/stanza/data_objects.html'''#初始化中文管道nlp=stanza.Pipeline('zh')#在表格中添加“是否存在特定词性”和“特定词性”两列sheet.cell(row=1,column=6,value="是否存在特定词性")sheet.cell(row=1,column=7,value="特定词性")#读取表格中的B列数据,并在第6列标记每个单元格中是否存在特定词性,在第7列输出特定词性fori,cellinenumerate(sheet['B'],start=1):ifi==1:continue#跳过标题行doc=nlp(cell.value)flag=Falsespecial_pos_list=[]forwordindoc.sentences[0].words:ifword.uposin['ADV','DET','ADJ','NUM']:flag=Truespecial_pos_list.append(f"【{word.upos}】{word.text}")sheet.cell(row=i,column=6,value="是"ifflagelse"否")sheet.cell(row=i,column=7,value=",".join(special_pos_list))#加载Stanza语言模型,进行中文数词、副词、形容词分析"defload_stanza_to_sheet():wb=openpyxl.load_workbook(get_save_path_xlsx_file())#获取Sheet1、Sheet2和Sheet3表格对象#sheet1=wb['今日头条热榜']#在Sheet1中添加特定词性列#add_special_pos_columns(sheet1)#遍历工作表名称并添加特殊词性列forsheet_namein['今日头条热榜','抖音时事热榜','微博热搜']:sheet=wb[sheet_name]add_special_pos_columns(sheet)#保存Excel工作簿wb.save(get_save_path_xlsx_file())defmain():result_list=fenmenbielei()load_stanza_to_sheet()print("\n热搜词性分析已加载完成,现开始计算各表热搜的指数、文本情感的平均值\n")#使用zip函数可以将数组打包为一个迭代器forsheet_name,resultinzip(['今日头条热榜','抖音时事热榜','微博热搜'],result_list):average_index,sentiment_score=resultprint(f'{sheet_name}平均指数:{average_index:.2f}情感得分:{sentiment_score:.2f}')print("\n")#如果当前模块是被其他模块导入的,则该条件语句下面的代码将不会被执行。if__name__=='__main__':main()