Python爬虫与信息提取(五)爬虫实例:爬取新浪微博热搜排名

news/2025/3/29 20:37:08/

经过一段时间的Python网络爬虫学习,今天自己摸索制作了一个能够爬取新浪微博实时热搜排名的小爬虫

1.效果:

2.制作过程中遇到的问题:

(1)一开始研究微博热搜页面的源代码时忽略了<tbody>中还包括一个置顶热搜,它的标签包含结构和其他的50个不同,因此需要单独考虑

(2)难点是标签中信息的获取,需要搞清楚 find_all( ) 函数返回的是列表,只能用于for遍历体系中,针对HTML中的<tbody>下面的<tr>节点,<tr>下面的<tb>子节点,都需要一步一步地find

(3)在一开始不知道如何使用class="td-01"属性直接find到内容,因为python的关键字class会和class=发生重名的情况,经过查阅之后发现,可以使用 class_ 代替 class

https://blog.csdn.net/IMW_MG/article/details/78109199

(4)在获取的时候曾经遇到了问题:使用<>.string获取不到标签中的字符串内容,这种情况会在热搜排名中带有表情emoji时发生,经过调试得到了将string替换为text的解决方法,可以正常地得到字符串的内容

(5)正确地获取到一个存储信息的二维列表之后,还需要按照格式从而正确地打印出来,这又是一个难点。一直遇到了一个问题:在中英混合的字符串中,内置的len( )函数无法正确地计算字符串的字符长度(不是长度!),从而导致了输出排版不整齐的问题。经过查阅之后,有下面的内容解决了这样的问题:

https://www.jb51.net/article/86577.htm

 于是内建了函数length( )来正确获取字符串的字符宽度,从而正确计算所需空格的数量

#获取一个中英文混合的字符串文本的字符宽度部分
widths = [(126,  1), (159,  0), (687,   1), (710,  0), (711,  1),(727,  0), (733,  1), (879,   0), (1154, 1), (1161, 0),(4347,  1), (4447,  2), (7467,  1), (7521, 0), (8369, 1),(8426,  0), (9000,  1), (9002,  2), (11021, 1), (12350, 2),(12351, 1), (12438, 2), (12442,  0), (19893, 2), (19967, 1),(55203, 2), (63743, 1), (64106,  2), (65039, 1), (65059, 0),(65131, 2), (65279, 1), (65376,  2), (65500, 1), (65510, 2),(120831, 1), (262141, 2), (1114109, 1),
]
def get_width(a):global widthsif a == 0xe or a == 0xf:return 0for num, wid in widths:if a <= num:return widreturn 1
def length(str):sum = 0for ch in str:sum += get_width(ord(ch))return sum

3.全部代码

import requests
import re
import bs4#获取一个中英文混合的字符串文本的字符宽度部分
widths = [(126,  1), (159,  0), (687,   1), (710,  0), (711,  1),(727,  0), (733,  1), (879,   0), (1154, 1), (1161, 0),(4347,  1), (4447,  2), (7467,  1), (7521, 0), (8369, 1),(8426,  0), (9000,  1), (9002,  2), (11021, 1), (12350, 2),(12351, 1), (12438, 2), (12442,  0), (19893, 2), (19967, 1),(55203, 2), (63743, 1), (64106,  2), (65039, 1), (65059, 0),(65131, 2), (65279, 1), (65376,  2), (65500, 1), (65510, 2),(120831, 1), (262141, 2), (1114109, 1),
]
def get_width(a):global widthsif a == 0xe or a == 0xf:return 0for num, wid in widths:if a <= num:return widreturn 1
def length(str):sum = 0for ch in str:sum += get_width(ord(ch))return sum#获取HTML文本
def getHTMLText(url):try:#模拟浏览器kv = {'user-agent':'Mozilla/5.0'}r = requests.get(url, headers=kv, timeout=30)  r.raise_for_status()r.encoding = r.apparent_encodingreturn r.textexcept:print("InternetError!")return " "#解析并且返回HTML文本
def HTMLTextconvert(html):try:soup = bs4.BeautifulSoup(html, "html.parser")return soupexcept:print("HTMLConvertError!")return " "#检索HTML中的信息,获取搜索排名信息
#存在置顶的情况,需要特殊判断
def HTMLSearch(html, ranklist):try:flag = 0#找到所有tbody标签下的所有内容,并且遍历所有的儿子节点for tr in html.find("tbody").children:#添加判断:获得的内容是否为标签Tag类型if isinstance(tr, bs4.element.Tag):#使用flag特判置顶的情况if flag==0:rank = "置顶"#注意由于class属性会和python中的关键字重名,因此需要变为class_td02 = tr.find_all(class_=re.compile('td-02'))for i in td02:if isinstance(i, bs4.element.Tag):#trans得到的类型为列表trans = i.find_all("a")number = " "ranklist.append([rank, trans[0].string, number])flag = 1else:#排名信息在td标签下的class=td-01属性中td01 = tr.find_all(class_=re.compile("td-01"))for i in td01:if isinstance(i, bs4.element.Tag):rank = i.string#热搜内容和搜索量在td标签下的class=td-02属性中:内容是a标签,搜索量是span标签td02 = tr.find_all(class_=re.compile("td-02"))for i in td02:name = i.find_all("a")column = i.find_all("span")#使用string获取字符串信息不准确,因为微博还有一些热搜标题为含有表情的,因此使用了textranklist.append([rank, name[0].text, column[0].text])except:print("HTMLSearchError!")#打印排名
def Rankprint(ranklist, num):try:#先打印表头,总长为70个字符,其中{1}和{3}是变化的空格数量计算,默认为:#排名*4,空格*3,名称*50,空格*5,点击量*8a = " "print("——————————————————————————————————————")print("{0}{1}{2}{3}{4}\n".format("排名", a*5, "热搜内容", a*45, "搜索量"+a*2))#使用flag来判断是否输出了置顶内容flag = 0for i in range(num):if flag==0:print("{0}{1}{2}\n".format(ranklist[i][0], a*3, ranklist[i][1]))flag = 1else:#c是排名有一位、两位的数字,用来纠正空格c = 7-len(ranklist[i][0])#根据内容来随时计算所要填充的空格数量bstr = ranklist[i][1]b = 62-length(ranklist[i][1])-len(ranklist[i][0])-cprint("{0}{1}{2}{3}{4:<8}".format(ranklist[i][0], a*c, ranklist[i][1], a*b, ranklist[i][2]))print("\n")except:print("RankPrintError!")#主函数
def main():try:#微博热搜的网站url = "https://s.weibo.com/top/summary?Refer=top_hot&topnav=1&wvr=6"#使用二维列表存储每一条热搜信息的rank信息和内容rank = []text = getHTMLText(url)soup = HTMLTextconvert(text)HTMLSearch(soup, rank)Rankprint(rank, 51)except:print("SystemError!")return 0
main()

在所有可能发生错误的部分都增加了报错机制,这样程序就更加的具有适应能力了!

 


http://www.ppmy.cn/news/386897.html

相关文章

ANR原理及分析

ANR 基础知识 ANR&#xff08;Application Not Responding&#xff09;的监测原理本质上是消息机制&#xff0c;设定一个delay消息&#xff0c;超时未被移除则触发ANR。具体逻辑处理都在system server端&#xff0c;包括发送超时消息&#xff0c;移除超时消息&#xff0c;处理…

图数据库游记

图数据库游记 起因 似乎一直都想有这样一种工具,能够将所学到的知识和生活中的数据都表示和存储在计算机里面,并且能够在合适的时候调出来进行对比并且连接不同的领域发现数据之间的潜在联系.图数据库也是几年前听说过的,当时还以为是这个图指的是位图bitmap,实则指graph,最近…

74LS273芯片介绍

74LS273是8位数据/地址锁存器&#xff0c;它是一种带清除功能的8D触发器 &#xff0c; D0&#xff5e;D7为数据输入端&#xff0c;Q0&#xff5e;Q7为数据输出端&#xff0c;正脉冲触发&#xff0c;低电平清除&#xff0c;常用作数据锁存器,地址锁存器。 &#xff08;1&#xf…

74 系列COMS系列逻辑器件芯片功能大全

74 系列COMS系列逻辑器件芯片功能大全 74系列: 74LS00 TTL 2输入端四与非门 74LS01 TTL 集电极开路2输入端四与非门 74LS02 TTL 2输入端四或非门 74LS03 TTL 集电极开路2输入端四与非门 74LS04 TTL 六反相器 74LS05 TTL 集电极开路六反相器 74LS06 TTL 集电极开路六反…

74系列标准逻辑集成芯片分类

74系列集成电路&#xff0c; 按工艺特点进行划分&#xff0c;逻辑器件可以分为Bipolar、CMOS、BiCMOS等工艺&#xff0c;其中包括器件系列有&#xff1a; Bipolar&#xff08;双极&#xff09;工艺的器件有&#xff1a; TTL、S、AS、LS、ALS、F。&#xff08;除了标准型和高速型…

74ls系列芯片的分类

最近在学数字电路,对芯片的编号不知道是什么意思:网上查了一下,记下以便日后查询: 74ls00 2输入四与非门 74ls01

java static 关键字

java 中常用的关键字有&#xff1a;final、static、extends、super、abstract、interface、implements。下面讲述 static 这个关键字。 static 翻译成中文静态的&#xff0c;java 中主要用于内存管理。 用 static 修饰的成员变量、方法、代码块、内部类是类纬度的&#xff0c;非…

大语言模型高质量提示词最佳实践

大语言模型高质量提示词最佳实践 一、提供更清晰的指令 使用大语言模型&#xff08;类似ChatGPT、Bard等工具&#xff09;的过程中&#xff0c;一个关键的技巧是能够给出清晰和明确的指令。大语言模型的运作方式是根据提供的输入&#xff0c;预测接下来应该生成什么内容。因此…