首页 > 编程 > Python > 正文

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

2019-11-25 15:08:46
字体:
来源:转载
供稿:网友

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

#!/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 ''' 

保存到数据库

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)]) 

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表