python正则表达式爬取猫眼电影top100

时间:2021-09-19 09:03:09

正则表达式爬取猫眼电影top100,具体内容如下

?
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import json  # 快速导入此模块:鼠标先点到要导入的函数处,再Alt + Enter进行选择
from multiprocessing.pool import Pool #引入进程池
 
import requests
import re
import csv
from requests.exceptions import RequestException #引入异常
 
## 正确保存,无丢失
 
# 请求一个页面返回响应内容
#以《霸王别姬》为列,右击—查看元素—会显示一个网页信息
def get_one_page(url,offset):
 try:
  response=requests.get(url=url,params={"offset":offset})
  if response.status_code==200: #由状态码判断返回结果,200表示请求成功,300,500表出错
   return response.text #返回网页内容
  else:return None
 except RequestException as e:
   return None
 
# 解析一个页面
def parse_one_page(html):
 pattern = ('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
       + '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
       + '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>')
 #写个正则,匹配所有结果。这里由上面的网页相应内容写<dd>开头,.*?匹配任意字符穿 board-index匹配标识符,类名,
 # \d 表数字即排名,'+'表示匹配至少一个可多个数字,</i>右边结束符
 #“?”,问号表示 非贪婪匹配,就是一旦匹配到就不在继续往后面尝试。
 #而\(和\)分别表示匹配一个“(”和“)”
 # re.S匹配多行
 regex = re.compile(pattern,re.S) #一个方法,通过一个正则表达式字符串编译生成一个正则表达式对象,re.S 匹配任意字符
 items = regex.findall(html) #以列表形式返回全部能匹配的子串. eg: re.findall(pattern, string[, flags])
 for item in items: #将结果以字典形式返回,键值对
   yield#把这个方法变成一个生成器
    'index':item[0],
    'image':item[1],
    'title':item[2],
    'actor':item[3].strip()[3:], #用strip()去掉换行符,不想要 主演: 这三个字就用[3:]组成一个切片,name就可以将前三个字符串去掉
    'time':get_release_time(item[4].strip()[5:]),  #去掉前五个字符
    'area':get_release_area(item[4].strip()[5:]),
    'score':item[5]+item[6] #将评分整数部分和小数部分结合起来
  }
 
'''''
#保存到txt,会发现中文汉字变成了unic的编码,加上encoding='utf-8',ensure_ascii=False,则汉字可正常输出
def write_to_file(content):
 with open('result.txt','a',encoding='utf-8') as f: # 参数 a ,表示直接往后追加
  f.write(json.dumps(content,ensure_ascii=False) +'\n') #content是一个字典的形式,用json.dumps 把它转换为字符串,再加个换行符
  f.close() 
#json.dumps :dict 转换为 str
#json.loads: str 转换为 dict
'''
''''''''
# 获取上映时间 <p class="releasetime">上映时间:1993-01-01(中国香港)</p>
def get_release_time(data):
 pattern = '^(.*?)(\(|$)'
 regex = re.compile(pattern)
 w = regex.search(data)
 return w.group(1) # group(1)指的是第一个括号里的东西
 
# 获取上映地区
def get_release_area(data):
 pattern = '.*\((.*)\)' #而\(和\)分别表示匹配一个 '(' 和 ')'
 regex = re.compile(pattern)
 w = regex.search(data)
 if w is None:
  return'未知'
 return w.group(1)
 
# 获取封面大图,不需要
# def get_large_thumb(url):
#  pattern = '(.*?)@.*?'
#  regex = re.compile(pattern)
#  w = regex.search(url)
#  return w.group(1)
 
# 存储数据
def store_data(item):
 with open('movie.csv','a',newline='',encoding='utf-8') as data_csv:
  # dialect为打开csv文件的方式,默认是excel,delimiter="\t"参数指写入的时候的分隔符
  csv_writer = csv.writer(data_csv)
  csv_writer.writerow([item['index'], item['image'], item['title'], item['actor'],item['time'],item['area'],item['score']])
# 参数newline是用来控制文本模式之下,一行的结束字符。可以是None,'',\n,\r,\r\n等。
'''''
也可判断异常,一般没错
  try:
   csv_writer = csv.writer(data_csv)
   csv_writer.writerow([item['index'], item['image'], item['title'], item['actor'],item['time'],item['area'],item['score']])
  except Exception as e:
   print(e)
   print(item)
'''
 
# 下载封面图
#读方式打开的话,并不会新建;写方式打开的话就会新建。 r只读,w可写,a追加
def download_thumb(title,image):
 try:
  response = requests.get(image)
  # 获取二进制数据
  with open('image/'+title+'.jpg', 'wb') as f: #将封面图保存到当前路径下的image文件夹中,图片名称为:电影名.jpg
   f.write(response.content)
   f.close()
 except RequestException as e:
  print(e)
  pass
 
 
# 主调度程序
def main():
 # 起始URL
 start_url = 'http://maoyan.com/board/4?'
 for i in range(0,1000,10):
  # 获取响应文本内容
  html = get_one_page(url=start_url, offset=i)
  if html is None:
   print('链接:%s?offset=%s异常'.format(start_url,i))
   continue
  for item in parse_one_page(html):
   # print(item)
   store_data(item)
   # download_thumb(item['title'],item['image'])
#
 
if __name__=='__main__':
 main()
 
'''''
if __name__=='__main__':
 for i in range(10):
  main(i*10)
'''
 
'''''
if __name__=='__main__':
 for i in range(10):
  main(i*10)
 pool=Pool() #可以提供指定数量的进程供用户调用,如果有一个新的请求被提交到进程池,进程池还没有满,就会创建新的进程来执行请求,如果满了,就先等待
 pool.map(main,[i*10 for i in range(10)]) #将数组中的每一个元素拿出来当做函数的参数,然后创建一个个的进程,放到进程池里面去运行;第二个参数是构造一个数组,组成循环
 #速度明显变快!1s
'''

保存到数据库

?
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
def main(offset):
  url='http://maoyan.com/board/4?offset='+str(offset)
  html=get_one_page(url)
  # for item in parse_one_page(html):
  #   print(item['number'])  #能正确输出 , charset="utf8"
  try:
    conn = pymysql.connect(host='localhost', user='root', passwd=' ', port=3306,db='test1',charset="utf8",use_unicode = False )
    cur = conn.cursor() # 创建一个游标对象
    for item in parse_one_page(html):
      try:
        # sql = "INSERT INTO movies (number,picture,title,actors,time,area,score) VALUES (%s,%s,%s,%s,%s,%s,%s)"
        # cur.execute(sql, ( item['number'],item['picture'],item['title'],item['actors'],item['time'],item['area'],item['score']))
        sql = "insert into test_movies (number,picture,title,actors,time,area,score) values(%s,%s,%s,%s,%s,%s,%s)"
        cur.execute(sql, (item['number'], item['picture'], item['title'], item['actors'], item['time'], item['area'],item['score']))
      except pymysql.Error as e:
        print(e)
      print('- - - - - 数据保存成功 - - - - -')
    conn.commit()
    cur.close()
    conn.close() # 关闭数据
  except pymysql.Error as e:
    print("Mysql Error %d: %s" % (e.args[0], e.args[1]))
 
 
if __name__=='__main__':
  # 连接数据库
  conn = pymysql.connect(host='localhost', user='root', passwd=' ', port=3306, db='test1', charset="utf8")
  cur = conn.cursor() # 创建一个游标对象
  cur.execute("DROP TABLE IF EXISTS test_movies") # 如果表存在则删除
  # 创建表sql语句
  sqlc = """CREATE TABLE test_movies(
    number int not null primary key auto_increment,
    picture VARCHAR(100) NOT NULL,
    title VARCHAR(100) NOT NULL,
    actors VARCHAR(200) NOT NULL,
    time VARCHAR(100) NOT NULL,
    area VARCHAR(100) ,
    score VARCHAR(50) NOT NULL
  )"""
  cur.execute(sqlc) # 执行创建数据表操作
  pool=Pool()
  pool.map(main,[i*10 for i in range(10)])

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://blog.csdn.net/sisteryaya/article/details/77899539