前言

前段时间应我姐邀请,看了一下Python爬虫。不得不说Python的语法确实简洁优美,可读性强,比较接近自然语言,非常适合编程的初学者上手。

在开始之前还是先介绍下什么是爬虫:

网络爬虫(英语:web crawler),也叫网络蜘蛛(spider),是一种用来自动浏览万维网的网络机器人。 – 维基百科

爬虫是一种程序或者脚本,用来替代人工浏览网页并从中提取信息,通常将提取的信息存储然后对其进行分析,从而获取有价值的信息。

爬虫也不是什么新鲜事物,可以说只要是编程语言几乎都能做到,而Python因为其简洁的语法和丰富的第三方库可以快速高效的编写爬虫,对于初学者可以说相当友好。接下来以爬取豆瓣电影TOP250页面为例说明如何用Python实现爬虫和数据可视化。

实现步骤

一、HTTP请求

导入第三方库requests,调用requests.get()方法向豆瓣电影TOP250页面发起GET请求,拿到响应的HTML。

二、数据提取

浏览器访问豆瓣电影TOP250页面并进入开发者模式复制要抓取节点的XPath。导入第三方库lxml的etree对象,调用etree.HTML(HTML)将HTML转换成element对象,然后使用element.xpath(XPath)方法拿到抓取的节点的文本(PS:也可以使用正则匹配文本)。

三、数据存储

导入第三方库openpyxl,调用openpyxl.Workbook()方法获取一个新的工作簿workbook,写入workbook.active=sheet获得一个工作表的引用sheet,为excel表指定位置添加数据:sheet[“A1”]=value,最后使用workbook.save(”excel表名“)保存数据,这里不用数据库是为了方便没有编程基础也能查看数据。

四、继续爬取

根据爬取页面的URL参数重复以上步骤,如豆瓣电影TOP250有两个参数start和filter,start表示页面的电影排行从TOP几的后一个开始,每个页面有25个电影,也就是说第一个页面参数start=0,第二个页面参数start=25,filter为过滤,暂时不用管,请求下一个页面时GET请求的参数start+25即可。

五、数据可视化

调用openpyxl.load_workbook(“excel表名”)方法获取存放数据的excel表,写入workbook.active=sheet获得一个工作表的引用,获取excel表指定位置的数据:data=sheet[“A1”].value。然后导入第三方库pyecharts,并根据文档调用合适的API生成图表实现数据可视化。

爬虫开发

创建一个项目Crawler,安装使用的第三方库:

1
2
3
4
pip install requests
pip install lxml
pip install openpyxl
pip install pyecharts

接下来在项目目录下新建文件html_parser.py:

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
from lxml import etree


class HTMLParser: # HTML解析类
def __init__(self):
pass

# 返回豆瓣电影Top250页面特定序号的电影的相关数据
def parse(self, html, number):
movie = {"title": "", "actors": "", "classification": "", "score": "", "quote": ""}
selector = etree.HTML(html)
movie["title"] = selector.xpath(
'//*[@id="content"]/div/div[1]/ol/li[' + str(number) + ']/div/div[2]/div[1]/a/span[1]/text()')[0]
movie["actors"] = selector.xpath(
'//*[@id="content"]/div/div[1]/ol/li[' + str(number) + ']/div/div[2]/div[2]/p[1]/text()[1]')[0]
movie["classification"] = selector.xpath(
'//*[@id="content"]/div/div[1]/ol/li[' + str(number) + ']/div/div[2]/div[2]/p[1]/text()[2]')[0]
movie["score"] = selector.xpath(
'//*[@id="content"]/div/div[1]/ol/li[' + str(number) + ']/div/div[2]/div[2]/div/span[2]/text()')[0]
# 如果存在则为该值,否则为空
movie["quote"] = selector.xpath(
'//*[@id="content"]/div/div[1]/ol/li[' + str(number) + ']/div/div[2]/div[2]/p[2]/span/text()')[0] if len(
selector.xpath('//*[@id="content"]/div/div[1]/ol/li[' + str(
number) + ']/div/div[2]/div[2]/p[2]/span/text()')) > 0 else ""
return movie

该模块封装了解析豆瓣电影TOP250页面并提取数据的方法。

然后同样新建文件excel_handler.py:

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
39
40
41
42
43
import openpyxl


class ExcelHandler: # excel文件处理类
__book = None
__sheet = None

def __init__(self):
self.book = None
self.sheet = None
pass

# 获取工作簿并获得工作表的引用
def startHandleExcel(self):
self.book = openpyxl.Workbook()
self.sheet = self.book.active

# 为A、B、C、D、E列的指定行添加数据
def handleExcel(self, row, A, B, C, D, E):
self.sheet["A" + str(row)] = str(A).strip()
self.sheet["B" + str(row)] = str(B).strip()
self.sheet["C" + str(row)] = str(C).strip()
self.sheet["D" + str(row)] = str(D).strip()
self.sheet["E" + str(row)] = str(E).strip()
return True

# 处理完成保存excel
def endHandleExcel(self, fileName):
self.book.save(fileName)

# 读取excel并获得工作表的引用
def startReadExcel(self, fileName):
self.book = openpyxl.load_workbook(fileName)
self.sheet = self.book.active

# 读取excel指定位置的数据
def readExcel(self, coordinate):
return str(self.sheet[coordinate].value)

# 读取完成
def endReadExcel(self):
pass

该模块封装了存储和读取excel表的方法。

接下来在mian.py中写入:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import requests
import random
import time

from html_parser import HTMLParser
from excel_handler import ExcelHandler
from pyecharts import options as opts
from pyecharts.charts import Bar


def crawling(): # 爬取豆瓣电影Top250函数
# 定义当前处理的excel表的行
excelRow = 1
# 实例化excel处理类
excelHandler = ExcelHandler()
# 开始处理excel
excelHandler.startHandleExcel()
# 在excel表中添加标题行
excelHandler.handleExcel(excelRow, "名字", "演员", "分类", "评分", "引言")
# 处理的行+1
excelRow += 1

# 定义豆瓣电影Top250页面的地址和所使用的user-agent(伪装为正常浏览器)
url = "https://movie.douban.com/top250"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/89.0.4389.82 Safari/537.36"}
# 实例化网页解析类
htmlParser = HTMLParser()
print("开始爬取豆瓣电影Top250...")
# 爬取豆瓣电影Top250的十个网页
for page in range(10):
# 定义URL的参数
param = {"start": page * 25, "filter": ""}
# 发起GET请求
response = requests.get(url=url, params=param, headers=headers).text
# 将请求结果页的25个电影信息存入excel
for list in range(25):
print("正在处理" + str(page + 1) + "页的第" + str(list + 1) + "部电影...")
# 解析电影的信息
movie = htmlParser.parse(response, list + 1)
# 将解析结果存入excel
excelHandler.handleExcel(excelRow, movie["title"], movie["actors"], movie["classification"], movie["score"],
movie["quote"])
# 处理的行+1
excelRow += 1
print("第" + str(page + 1) + "页爬取完成!")
# 等待5-20秒之后再次爬取,模拟人的操作
time.sleep(random.randint(5, 20))
# excel存入完成
excelHandler.endHandleExcel("movies.xlsx")
print("豆瓣电影Top250爬取完成!")


def getCharts(): # 绘制评分数据图函数
# 定义评分的字典
scoreLevel = {}
# 实例化excel处理类
excelHandler = ExcelHandler()
# 开始读取excel表
excelHandler.startReadExcel("movies.xlsx")
print("开始读取excel表中的评分列...")
# 循环遍历excel表评分列
for row in range(250):
# 从excel表中读取评分列作为字典的key
key = excelHandler.readExcel("D" + str(row + 2))
# 如果该key存在则+1
if key in scoreLevel:
scoreLevel[key] += 1
# 否则初始化该key的值为1
else:
scoreLevel[key] = 1
# 读取excel结束
excelHandler.endReadExcel()

# 定义一个列表表示scoreLevel字典所有的key(即评分)
keys = []
# 定义一个列表表示scoreLevel字典所有的value(即该评分的数量)
values = []
# 提取scoreLevel的key和value
for key in scoreLevel:
keys.append(key)
values.append(scoreLevel[key])
print("评分数据读取完成!")

print("开始绘制评分数据图...")
# 绘制柱状图
c = (
Bar()
.add_xaxis(keys)
.add_yaxis("评分:数量(部)", values)
.set_global_opts(
title_opts=opts.TitleOpts(title="豆瓣电影评分Top250"),
toolbox_opts=opts.ToolboxOpts(),
legend_opts=opts.LegendOpts(is_show=False),
)
.render("movies_score.html")
)
print("评分数据图绘制完成!")


# 爬取豆瓣电影TOP250
crawling()

# 绘制评分数据图
getCharts()

main.py中的两个函数分别实现爬取豆瓣电影TOP250并存储数据和读取数据进行数据可视化操作,具体的过程已在注释中详细标注。

源码

Gitee: python-crawler

Github: python-crawler

相关链接

requests

lxml

openpyxl

pyecharts

Python 网络爬虫之Requests库的基本用法

python–lxml.etree解析html

Openpyxl 教程

最后

Python有很多优秀的爬虫框架,有兴趣可以自行了解,例如:

8个最高效的Python爬虫框架,你用过几个?

但是爬虫不是什么内容都可以爬取,所谓”爬虫写的好,监狱进的早”,在爬取内容之前得先看一下

等相关规范和限制。