200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > Python爬虫与信息提取(五)爬虫实例:爬取新浪微博热搜排名

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

时间:2023-02-16 19:00:01

相关推荐

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

经过一段时间的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

/IMW_MG/article/details/78109199

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

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

/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 1def length(str):sum = 0for ch in str:sum += get_width(ord(ch))return sum

3.全部代码

import requestsimport reimport 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 1def 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_=pile('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_=pile("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_=pile("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 = "/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 0main()

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。