爬虫-数据持久化

这篇文章主要是将请求下来的数据,进行数据分析,并且进行存储

数据解析

数据的分类

  1. 结构化数据
    特点 :有固定的格式,如:HTML、XML、JSON
  2. 非结构化数据
    示例 :图片、音频、视频,这类数据一般存储为二进制

正则表达式 re

使用流程

1
2
3
1、创建编译对象 :p = re.compile('正则表达式')
2、对字符串匹配 :r = p.match("字符串")
3、获取匹配结果 :print(r.group())

常用方法

  1. match(s) : 字符串开头的第1个,返回对象
  2. search(s): 从开始往后找,匹配第1个满足的,返回对象
  3. findall(s):所有全部匹配,返回一个列表

表达式

字符 含义
. 任意字符(不包括\n)
\d 数字
\s 空白字符
\S 非空白字符
[…] 包含[]内容 A[BCD]E -> ABE ACE ABCE
\w 字母、数字、_
* 0次或n次
0次或1次
+ 1次或n次

贪婪匹配和非贪婪匹配

贪婪匹配(.*) : 在整个表达式匹配成功的前提下,尽可能多的匹配 *
非贪婪匹配(.*?) : 在整个表达式匹配成功的前提下,尽可能少的匹配 *

re.S 让 . 能够匹配\n在内的所有字符

findall的分组

1.分组示例
先按照正则整体匹配出来,然后再匹配()中的
如果正则中有多个(),则以元组形式显示

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
import re

s = "A B C D"
p1 = re.compile('\w+\s+\w+')
print(p1.findall(s))

# 1. 先匹配整体正则 ['A B','C D']
# 2. 再匹配正则()中的 ['A','C']
p2 = re.compile('(\w+)\s+\w+')
print(p2.findall(s))

# 1. 先按整体匹配 ['A B','C D']
# 2. 匹配正则()中的,多个()放到元组中
p3 = re.compile('(\w+)\s+(\w+)')
print(p3.findall(s))
```

2.正则分组练习
``` py
import re

html = """<div class="animal">
<p class="name">
<a title="Tiger"></a>
</p>

<p class="content">
Two tigers two tigers run fast
</p>
</div>

<div class="animal">
<p class="name">
<a title="Rabbit"></a>
</p>

<p class="content">
Small white rabbit white and white
</p>
</div>"""
p = re.compile('<div class="animal">.*?title="(.*?)".*?class="content">(.*?)</p>.*?</div>',re.S)
r_list = p.findall(html)
#print(r_list)

for r_tuple in r_list:
print("动物名称:",r_tuple[0].strip())
print("动物描述:",r_tuple[1].strip())
print("*" * 20)

案例1 :内涵段子脑筋急转弯抓取

  1. 网址 :https://www.neihan8.com/

  2. 目标 :段子 - 脑筋急转弯 - 题目、答案

  3. 步骤

    1. 找URL规律
    1
    2
    3
    第1页:https://www.neihan8.com/njjzw/
    第2页:https://www.neihan8.com/njjzw/index_2.html
    第n页:https://www.neihan8.com/njjzw/index_n.html
    1. 写正则
    1
    <div class="text-column.*?title="(.*?)".*?<div class="desc">(.*?)</div>
    1. 写代码
    1
    2
    3
    1、获取页面
    2、解析页面
    3、保存数据

代码

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
import urllib.request
import re

class NeihanSpider:
def __init__(self):
self.headers = {"User-Agent":"Mozilla/5.0"}
self.baseurl = "https://www.neihan8.com/njjzw/"
self.page = 1

# 下载页面
def getPage(self,url):
req = urllib.request.Request(url,headers=self.headers)
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
self.parsePage(html)

# 解析页面
def parsePage(self,html):
p = re.compile('<div class="text-column.*?title="(.*?)".*?<div class="desc">(.*?)</div>',re.S)
r_list = p.findall(html)
# r_list : [("什么动物在墙上","海豹"),(),(),()]
self.writePage(r_list)

# 保存数据
def writePage(self,r_list):
for r_tuple in r_list:
for r_str in r_tuple:
with open("急转弯.txt","a") as f:
f.write(r_str.strip()+"\n")
with open("急转弯.txt","a") as f:
f.write("\n\n")

# 主函数
def workOn(self):
self.getPage(self.baseurl)
while True:
c = input("是否继续(y/n):")
if c.strip().lower() == "y":
self.page += 1
url = self.baseurl + "index_" + \
str(self.page) + ".html"
self.getPage(url)
print("第%d页爬取结束" % self.page)
else:
print("结束")
break

if __name__ == "__main__":
spider = NeihanSpider()
spider.workOn()

csv模块的使用

使用流程

1
2
3
4
5
6
1、打开csv文件
with open("test.csv","a",newline="") as f:
2、初始化写入对象
writer = csv.writer(f)
3、写入数据
writer.writerow(["英雄","梁朝伟","2000"])

注意

1、newline = “”
2、writer.writerow的参数一定要为列表

猫眼电影top100存入csv文件

  1. 网址 :猫眼电影 - 榜单 - TOP100榜

  2. 目标 :电影名称 、主演 、上映时间

  3. 步骤

    1. 规律
    1
    2
    3
    第1页:http://maoyan.com/board/4?offset=0
    第2页:http://maoyan.com/board/4?offset=10
    第n页:offset=(n-1)*10
    1. 写正则
    1
    <div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?class="releasetime">(.*?)</p>.*?</div>
    1. 写代码
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
import urllib.request
import re
import csv

class MaoyanSpider:
def __init__(self):
self.headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"}
self.baseurl = "http://maoyan.com/board/4?offset="
self.offset = 0

# 下载页面
def getPage(self,url):
req = urllib.request.Request(url,headers=self.headers)
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
self.parsePage(html)

# 解析页面
def parsePage(self,html):
p = re.compile('<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?class="releasetime">(.*?)</p>.*?</div>',re.S)
r_list = p.findall(html)
# r_list: [("英雄","梁朝伟","2000"),()]
self.writeTocsv(r_list)

# 保存数据到csv
def writeTocsv(self,r_list):
for r_tuple in r_list:
L = [r_tuple[0].strip(),r_tuple[1].strip(),r_tuple[2].strip()]
with open("TOP100.csv","a",newline="") as f:
# 初始化写入对象
writer = csv.writer(f)
writer.writerow(L)

# 主函数
def workOn(self):
while True:
c = input("爬取按y,退出按q:")
if c.strip().lower() == "y":
url = self.baseurl + str(self.offset)
self.getPage(url)
self.offset += 10
print("本页爬取成功")
else:
print("结束!")
break

if __name__ == "__main__":
spider = MaoyanSpider()
spider.workOn()