python3爬取古诗词
- 最近在学习python3基本的编程语法,python用起来代码很简洁(比java要清爽的多),看完官方文档,自己就像动手实践一下,做一个小小的检测
- 背景 本人酷爱古诗词,所以目标选择了
- 思路
- 通过观察网站的布局,在首页虽然有翻页的功能,但到100页就没了,不知道能不能爬下所有的古诗词。点击页面上方的 诗文,发现页面的右侧有很多分类,每个分类对应不同的url页面(ps:其实首页也有,但一开始就选择了诗文那个页面的右侧分类列表准备下手),目测能爬下所有的数据,所以从右面列表开始下手
- 查看页面布局(F12) 通过观察,右面列表的 类型包含完整的url,而 作者、 朝代、 形式这些的url并不全,同时这两种url打开的页面解析html也会不同。一个是直接列出所有的诗词名,再点击进入详情页;另一个是直接展示诗词,但分页
- 解析html选择最新的
requests-html
- 将解析后的数据保存到
mysql
- 多进程爬取数据
- 准备工作
- 安装
mysql-python
连接驱动模块 - 安装
requests-html
模块
- 安装
- 代码如下
- 导入需要使用的模块
import mysql.connectorfrom requests_html import HTMLSessionfrom multiprocessing import Pool
- 创建session
session = HTMLSession()
- 解析由 类型跳转的页面
def run_proc(url): print('参数:%s' % url) a = get(url).html.find('.main3', first=True).find('.left', first=True).find('.sons', first=True).find('a') result = [] for j in range(len(a)): url_info = 'https://so.gushiwen.org' + a[j].attrs['href'] print(url_info) val = parse_html(url_info, False, 'h1', True) if len(result) == 200: save_db(result) result = [] result.append(val[0]) if len(result) > 0: save_db(result)
- 解析由作者、 朝代、 形式跳转的页面
def run_proc_v2(url): print('参数:%s' % url) val = parse_html(url, True, 'b', False) result = val['result'] total = int(val['total']) page_no = (total + 9) // 10 url_split = url.split('.aspx')[0] prefix = url_split[:len(url_split) - 1] for i in range(1, page_no): page_url = prefix + str(i) + '.aspx' if len(result) == 200: save_db(result) result = [] r = parse_html(page_url, False, 'b', False) if len(r) > 0: for j in range(len(r)): result.append(r[j]) if len(result) > 0: save_db(result)
- 获取连接
def get(url): re = session.get(url) re.encoding = 'utf-8' return re
- 解析html
# 解析html# url:要解析的url# is_total 是否解析总数# title_node 诗词名html元素节点# flag 是否只解析一条def parse_html(url, is_total, title_node, flag): div = get(url).html.find('.main3', first=True).find('.left', first=True) sons = div.find('.sons') result = [] if sons is not None and len(sons) > 0: for i in range(len(sons)): values = [] son = sons[i] # title values.insert(0, son.find(title_node, first=True).text) # author source = son.find('.source', first=True).find('a') values.insert(1, source[1].text) # content values.insert(2, son.find('.contson', first=True).text) # dynasty values.insert(3, source[0].text) result.append(values) if flag: break # 解析总数 if is_total: total_str = div.find('.pages', first=True).find('span')[1].text total = total_str[1:len(total_str) - 1] val = {'result': result, 'total': total} return val else: return result
- 入库
def save_db(result): if result is not None and len(result) > 0: print('开始插入数据...') conn = mysql.connector.connect(user='root', password='wujinlei', host='127.0.0.1', port='3307', database='crawler') cursor = conn.cursor() for i in range(len(result)): values = result[i] cursor.execute('insert into poetry (title,author,content,dynasty) values (%s,%s,%s,%s)', values) conn.commit() print('已经插入%s条数据' % len(result)) cursor.close() conn.close()
- 主函数
if __name__ == "__main__": p = Pool(8) cate = get("https://www.gushiwen.org/shiwen/").html.find('.main3 .right', first=True).find('a') print(len(cate)) if cate is not None and len(cate) > 0: for i in range(len(cate)): c = cate[i] url = c.attrs['href'] if url[0] == '/': url = 'https://www.gushiwen.org' + url p.apply_async(run_proc_v2, args=(url,)) else: p.apply_async(run_proc, args=(url,)) p.close() p.join()
- 以上即是全部的代码,初步了解python,一些功能如进程等用的并不是很好,将就着看吧,如有错误,请沟通指出,一定虚心接受