nbtca's blog nbtca's blog
首页
技术
更多
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

nbtca

计协
首页
技术
更多
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • C语言

  • GO语言

  • Linux

  • Python

    • Python爬虫实战-获取王者荣耀英雄大全
    • Python爬虫实战 - 爬取TIOBE TOP20语言排行榜
      • Python爬虫实战 - 爬取TIOBE TOP20语言排行榜
        • 前置准备
        • 获取数据
        • 数据处理
  • 技术
  • Python
N3ptune
2022-04-05
目录

Python爬虫实战 - 爬取TIOBE TOP20语言排行榜

# Python爬虫实战 - 爬取TIOBE TOP20语言排行榜

URL: index | TIOBE - The Software Quality Company (opens new window)

IDE: PyCharm Professional

要爬取的是排名前20的语言榜单,并将其存成文本文件和生成词云。

python-spider-1

这个榜单包括6列,分别是2022年3月的排名(Mar 2022)、2021年3月的排名(Mar 2021)、增减、程序语言(Programming Language)、占比(Ratings)、变化率(Change)。

# 前置准备

导入要用的库:

import requests
from bs4 import BeautifulSoup
import re
import wordcloud
1
2
3
4

requests是用来发起https请求,并获取结果的。BeautifulSoup用于解析网页html代码,re用于正则匹配,wordcloud用于生成词云。

检查网页源代码,可以发现整个榜单放id为top20的table标签下:

python-spider-2

榜单的主体在这个table标签的tbody标签下:

python-spider-3

而每一行都被划分在tbody一个tr标签下:

python-spider-4

知道这些就足够了,下面编写代码。

# 获取数据

url = "https://www.tiobe.com/tiobe-index/"
res = requests.get(url)
soup = BeautifulSoup(res.text,"html.parser")
table = soup.find("table", id="top20").find("tbody").find_all("tr")
1
2
3
4

上述代码获取了网页html源码并解析,返回一个soup对象,使用find和find_all函数根据标签查找,获取tr标签下数据组成的列表。

接下来将其打印出来看看:

python-spider-5

打印出了每一个tr标签下的内容,要获取的数据就在其中:

for item in table:
    print(item.text)
1
2

那直接取出文本:

python-spider-6

现在拿到的数据就很间接了,程序将单个标签下所有的文本都连接到了一起。

现在已经获取到了数据,接下来要做的是数据处理。

# 数据处理

现在获取的仅仅是文本,接下来要对其进行分割。

这时派上用场的是正则表达式。

这里使用re模块中的search函数:

re.search(pattern, string, flags=0) # 扫描整个字符串并返回第一个成功的匹配。
1
参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等

不难发现,在上面爬到的文本中,每一行的第一个数字就是语言的当前排名(1,2,3...),因此这是固定的,后面紧跟的数字是去年排名,再跟着的若干单词是语言的名字,随后两个百分数就是占比和变化率。

那么每一次循环中,都是对一行的文本中数据的提取。

首先剔除每一行的第一个数字即当前排名,那么到字母之前剩下的数字就是去年排名,可以轻易的写出正则表达式"[0-9]+",来匹配第一个出现的纯数字。

随后就是语言名字了,直接匹配第一个非数字字符串即可,即"\D+"。

接下来要匹配占比,显然这个百分数后面都会跟着一个正号或负号,因此表达式可以写成

"(\d+.([0-9]?)%+)|(\d+.([0-9]?)%-)",最后剩下的是变化率,这个百分数之前都。有正负号,所以可以直接写出"-(.?)%|+(.?)%"。最后得到的结果用.group()函数取出即可。

每一行提取出的数据放到一个元组里:

current_rand = 1
for item in table:
    if current_rand < 10:
        target = item.text[1:]
    else:
        target = item.text[2:]
    previous_rand = re.search(r"[0-9]+", target).group()
    language = re.search(r"(\D)+", target).group()
    ratings = re.search(r"(\d+\.([0-9]*?)%\+)|(\d+\.([0-9]*?)%-)", target).group()[:-1]
    change = re.search(r"-(.*?)%|\+(.*?)%", target).group()
    current_rand = current_rand + 1
1
2
3
4
5
6
7
8
9
10
11

再循环中将结果打印:

python-spider-7

因为最后的结果要保存,所以要定义一个列表,将元组放到列表中。

考虑到要生成词云,所以同样要定义一个字典,与程序语言名称为key,以占比为值,这里要把百分比的%去掉,然后转化为浮点数:

words = {}
result = []
current_rand = 1
for item in table:
    if current_rand < 10:
        target = item.text[1:]
    else:
        target = item.text[2:]
    previous_rand = re.search(r"[0-9]+", target).group()
    language = re.search(r"(\D)+", target).group()
    ratings = re.search(r"(\d+\.([0-9]*?)%\+)|(\d+\.([0-9]*?)%-)", target).group()[:-1]
    change = re.search(r"-(.*?)%|\+(.*?)%", target).group()
    result.append((str(current_rand), previous_rand, language, ratings, change))
    words[language] = float(ratings.strip("%"))
    current_rand = current_rand + 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

得到列表后,保存文本文件:

f = open("result.txt", "w+")
f.write("Mar 2022  	Mar 2021  	Programming Language	Ratings	    Change\n")
for item in result:
    line = "{:<10}\t{:<10}\t{:<20}\t{:<10}\t{:<10}".format(item[0], item[1], item[2], item[3], item[4])
    f.write(line + "\n")
f.close()
1
2
3
4
5
6

上述代码中使用了格式化字符串,利用了format函数,利用open函数打开一个文件,指定标志为"w+",使用write函数向其中写入数据,使用close函数最后关闭文件。

如下是生成词云的代码,width和height指定长宽,background_color制定背景色:

w = wordcloud.WordCloud(width=1000, height=700, background_color="white")
w.generate_from_frequencies(words)
w.to_file("result.png")
1
2
3

generate_from_frequencies接收一个字典。

最后to_file生成最后的图片文件。

完整代码如下:

import requests
from bs4 import BeautifulSoup
import re
import wordcloud

url = "https://www.tiobe.com/tiobe-index/"
res = requests.get(url)
soup = BeautifulSoup(res.text,"html.parser")
table = soup.find("table", id="top20").find("tbody").find_all("tr")

words = {}
result = []
current_rand = 1
for item in table:
    if current_rand < 10:
        target = item.text[1:]
    else:
        target = item.text[2:]
    previous_rand = re.search(r"[0-9]+", target).group()
    language = re.search(r"(\D)+", target).group()
    ratings = re.search(r"(\d+\.([0-9]*?)%\+)|(\d+\.([0-9]*?)%-)", target).group()[:-1]
    change = re.search(r"-(.*?)%|\+(.*?)%", target).group()
    result.append((str(current_rand), previous_rand, language, ratings, change))
    words[language] = float(ratings.strip("%"))
    current_rand = current_rand + 1

f = open("result.txt", "w+")
f.write("Mar 2022  	Mar 2021  	Programming Language	Ratings	    Change\n")
for item in result:
    line = "{:<10}\t{:<10}\t{:<20}\t{:<10}\t{:<10}".format(item[0], item[1], item[2], item[3], item[4])
    f.write(line + "\n")
f.close()

w = wordcloud.WordCloud(width=1000, height=700, background_color="white")
w.generate_from_frequencies(words)
w.to_file("result.png")


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

最后生成了如下的文本文件:

python-spider-8

以及词云图片:

python-spider-9

编辑 (opens new window)
上次更新: 2024/03/29, 12:07:43
Python爬虫实战-获取王者荣耀英雄大全

← Python爬虫实战-获取王者荣耀英雄大全

最近更新
01
Go语言极限入门
04-19
02
Python爬虫实战-获取王者荣耀英雄大全
04-17
03
Linux笔记 - 进程
04-05
更多文章>
Theme by Vdoing | Copyright © 2023-2024
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式