前面讲了如何通过pymysql操作数据库,这次写一个爬虫来提取信息,并将数据存储到mysql数据库
1.爬取目标
爬取猫眼电影TOP100榜单
要提取的信息包括:电影排名、电影名称、上映时间、分数
2.分析网页HTML源码
可以看到每部电影信息都被包裹在一对<dd>...</dd>标签中,所以我们只需提取出一个标签对中的上述信息即可。使用正则表达式提取
3. 完整过程
这个例子有2个关键点:正则编写和数据处理(写进mysql数据库)
(1) 正则表达式的编写###
pattern = re.compile(r'
.*? (\d+).*?' # 匹配电影排名(加个?表示非贪婪匹配,不是匹配0次或1次) r' (.*?)' # 匹配电影名称 r'.*? (.*?) ' # 匹配上映时间 r'.*? (.*?)' # 匹配分数的整数位 r'.*? (.*?).*? ', re.S) # 匹配分数小数位,re.S表示跨行匹配 m = pattern.findall(html) # print(m)
使用findall()方法来匹配所有符合规则的字符,返回一个列表,下面是其中一页的匹配结果
(2)完整代码,注意get_data()函数是如何处理数据,然后通过write_sql()函数是写入数据库的
# coding: utf-8# author: hmkimport requestsimport reimport pymysqldef get_html(url, header): response = requests.get(url, headers=header) if response.status_code == 200: return response.text else: return Nonedef get_data(html, list_data): pattern = re.compile(r'
.*? (\d+).*?' # 匹配电影排名 r' (.*?)' # 匹配电影名称 r'.*? (.*?) ' # 匹配上映时间 r'.*? (.*?)' # 匹配分数的整数位 r'.*? (.*?).*? ', re.S) # 匹配分数小数位 m = pattern.findall(html) for i in m: # 因为匹配到的所有结果会以列表形式返回,每部电影信息以元组形式保存,所以可以迭代处理每组电影信息 ranking = i[0] # 提取一组电影信息中的排名 movie = i[1] # 提取一组电影信息中的名称 release_time = i[2] # 提取一组电影信息中的上映时间 score = i[3] + i[4] # 提取一组电影信息中的分数,这里把分数的整数部分和小数部分拼在一起 list_data.append([ranking, movie, release_time, score]) # 每提取一组电影信息就放到一个列表中,同时追加到一个大列表里,这样最后得到的大列表就包含所有电影信息def write_sql(data): conn = pymysql.connect(host='localhost', user='root', password='123456', db='test', charset='utf8') cur = conn.cursor() for i in data: """这里的data参数是指正则匹配并处理后的列表数据(是一个大列表,包含所有电影信息,每个电影信息都存在各自的一个列表中; 对大列表进行迭代,提取每组电影信息,这样提取到的每组电影信息都是一个小列表,然后就可以把每组电影信息写入数据库了)""" movie = i # 每组电影信息,这里可以看做是准备插入数据库的每组电影数据 sql = "insert into maoyan_movie(ranking,movie,release_time,score) values(%s, %s, %s, %s)" # sql插入语句 try: cur.execute(sql, movie) # 执行sql语句,movie即是指要插入数据库的数据 conn.commit() # 插入完成后,不要忘记提交操作 print('导入成功') except: print('导入失败') cur.close() # 关闭游标 conn.close() # 关闭连接def main(): start_url = 'http://maoyan.com/board/4' depth = 10 # 爬取深度(翻页) header = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Encoding": "gzip, deflate, sdch", "Accept-Language": "zh-CN,zh;q=0.8", "Cache-Control": "max-age=0", "Connection": "keep-alive", "Host": "maoyan.com", "Referer": "http://maoyan.com/board", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36"} for i in range(depth): url = start_url + '?offset=' + str(10 * i) html = get_html(url, header) list_data = [] get_data(html, list_data) write_sql(list_data) #print(list_data) # for i in list_data: # t = i # print(t)if __name__ == "__main__": main()
注意一点,在请求url时,加了headers,这里必须加,估计是网站做了限制,直接爬的话会失败,可能认出请求链接的不是一个人而是一只虫了
代码中注释写得很详细,不再过多描述了