爬取豆瓣Top250电影信息

具体步骤

针对每一页网页(每页有 25 条电影信息,共有 10 页):

  1. 爬取网页:指定待爬取网页的URL,模拟普通浏览器访问该网页时需要的HTTP请求头(尤其是 User-Agent 字段),通过 urllib 库发送请求并得到响应。若没有发生异常,则对响应正文进行读入(以UTF-8格式)
  2. 解析网页:通过 BeautifulSoup 库将响应正文中得到的网页解析为标签树对象。
  3. 提取信息:遍历指定的 Tag 标签,对应的是每一条电影信息。将其转换为字符串类型,再通过预先创建好的正则表达式对象,匹配需要的字段,并按照顺序存放到列表类型(或字典类型)

(所有页)所有电影信息存放到同一个列表(或字典)时:创建Excel表格(或数据库表),按照位置依次写入其中。

代码实现

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
106
107
108
109
110
from bs4 import BeautifulSoup  # 网页解析,获取数据
import re # 正则表达式,进行文字匹配
import urllib.request, urllib.error # 制定URL,获取网页数据
import xlwt # 进行excel操作

def main():
baseurl = "https://movie.douban.com/top250?start="
# 1.爬取网页
datalist = getData(baseurl)

savepath = "豆瓣电影Top250.xls"

# 3.保存数据
saveData(datalist, savepath)


# 获取指定单个URL的网页内容
def getSinglePage(url):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
} # 用户代理:告诉豆瓣服务器,我们是什么类型的浏览器。此时模拟浏览器的头部信息,向豆瓣服务器发送消息
request = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
# print(html)
except urllib.error.URLError as e:
if hasattr(e, "code"):
print(e.code)
if hasattr(e, "reason"):
print(e.reason)
return html

# 解析数据
def getData(baseurl):
datalist = []
# 影片详情的链接
regLink = re.compile(r'<a href="(.*?)">') # 创建正则表达式对象,.代表一个字符,*代表0或多个,?代表链接只出现一次或0次
# 影片图片的链接
regImgSrc = re.compile(r'<img.*src="(.*?)"', re.S) # re.S使得换行符包含在匹配字符字符中,若不使用re.S,则只在每一行内进行匹配,若一行没有,就换下一行重新开始匹配
# 影片的片名
regTitle = re.compile(r'<span class="title">(.*?)</span>')
# 影片的评分
regRating = re.compile(r'<span class="rating_num" property="v:average">(.*?)</span>')
# 评价人数
regCommentNum = re.compile(r'<span>(\d*)人评价</span>')
# 影片基本信息
regInfo = re.compile(r'<span class="inq">(.*?)</span>')
# 影片相关人员
regPeopleName = re.compile(r'<p class="">(.*?)</p>', re.S)

for i in range(0, 10): # 11页
url = baseurl + str(i * 25)
html = getSinglePage(url) # 保存获取到当前页面的HTML源码
soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all('div', class_="item"): # 查找符合要求的字符串"div.item"
# print(item)
itemStr = str(item) # 转换为字符串
filmInfo = [] # 保存一部电影的所有信息

filmLink = re.findall(regLink, itemStr)[0] # 正则表达式匹配指定的字符串
imgSrc = re.findall(regImgSrc, itemStr)[0]
filmTitle = re.findall(regTitle, itemStr)
rating = re.findall(regRating, itemStr)[0]
commentNum = re.findall(regCommentNum, itemStr)[0]
cTitle = ' '
oTitle = ' '
if len(filmTitle) == 2:
cTitle = filmTitle[0] # 添加电影第一个名称
oTitle = filmTitle[1].replace("/", "") # 去掉无关的符号,添加另外一个名称
else:
cTitle = filmTitle[0]
filmInq = re.findall(regInfo, itemStr)
if len(filmInq) != 0:
filmInq = filmInq[0]
else:
filmInq = " "
filmPeopleName = re.findall(regPeopleName, itemStr)[0]
filmPeopleName = re.sub(r'<br(\s+)?/>(\s+)?', " ", str(filmPeopleName)).strip()

filmInfo.append(rating)
filmInfo.append(cTitle)
filmInfo.append(oTitle)
filmInfo.append(commentNum)
filmInfo.append(filmPeopleName)
filmInfo.append(filmInq)
filmInfo.append(filmLink)
filmInfo.append(imgSrc)
datalist.append(filmInfo)
print(datalist)
return datalist

# 保存数据
def saveData(datalist, savepath):
workbook = xlwt.Workbook(encoding="utf-8", style_compression=0)
worksheet = workbook.add_sheet('第一页', cell_overwrite_ok=True) # 第二个参数用于覆写之前的内容
col = ("评分", "影片中文名", "影片外国名", "评价数", "概况", "引言", "影片详情链接", "影片海报链接")
for j in range(0, 8):
worksheet.write(0, j, col[j])
for i in range(0, 250):
print("第%d条" % i)
rowData = datalist[i]
for j in range(0, 8):
worksheet.write(i+1, j, rowData[j])
workbook.save(savepath)


if __name__ == "__main__":
main()

异步爬取 51job 特定岗位信息

具体步骤

对于异步请求:需要找到异步请求的链接并分析规律,获取返回的JSON数据并进行解析

对于 51job 网站,发送链接后得到的响应中,可以发现JSON信息(即岗位信息)隐藏在 <script> 标签。

对其JSON信息进行格式化,发现规律:

由此,通过 re 库,对特定字段 engine_search_result 进行匹配得到字符串

通过 json 库,会根据JSON格式要求,将该字符串转换为列表,而列表的每一元素为字典类型,对应JSON每一字段信息

代码实现

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
import json
import re # 正则表达式,进行文字匹配
import urllib.error # 制定URL,获取网页数据
import urllib.request


def main():
joburl = "https://search.51job.com/list/330000%252c030200,000000,0000,00,9,99,c%252B%252B,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare="
result = getSinglePage(joburl)
# print(result)
jsonsStr = re.findall(r"\"engine_search_result\":(.+?),\"jobid_count\"", result)
# 返回结果为list,匹配结果只有一个,故长度为1
# print(jsonsStr[0]) # 打印列表中的字符串:所有岗位(在当前页)的JSON串
jsonObj = json.loads(jsonsStr[0])
# 将字符串转换为 存放字典类型的列表 ,
for peo in jsonObj: # 遍历列表中每个岗位,每个岗位对应列表中的一个字典
# 每个字典存放该岗位的各项信息
print(peo["job_name"] + ":" + peo["company_name"])


# 获取指定单个URL的内容
def getSinglePage(url):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
} # 用户代理
request = urllib.request.Request(url, headers=head)
result = ""
try:
response = urllib.request.urlopen(request)
result = response.read().decode("gbk")
except urllib.error.URLError as e:
if hasattr(e, "code"):
print(e.code)
if hasattr(e, "reason"):
print(e.reason)
return result


if __name__ == "__main__":
main()
1
2
3
4
5
6
7
8
C++开发工程师:广州拓波软件科技有限公司
C++开发工程师:广东星舆科技有限公司
C++高级工程师:广州市华飞通达科技有限公司
C++开发工程师:广州市云景信息科技有限公司
C++/Qt高级软件工程师(双休、十三薪):广州晋原铭科技有限公司
C++音视频开发工程师:广州昆仑科技有限公司
C/C++开发工程师:广州广有通信设备有限公司
...