本文主要介绍使用Python爬虫爬取Python百度词条的信息 主要参考慕课网的《开发简单爬虫》以及一些数据库操作
开发工具
—工欲善其事 必先利其器
首先 这里开发工具用的Python3.6+Pycharm+MySQL5.7+SQLyog
前面2个的安装直接网上搜下教程一大堆 而且免去了配置环境变量的操作,MySQL数据库(安装教程也一大堆)现在最新版是5.7 它的安装与之前的有点不同
本文主要介绍使用Python爬虫爬取Python百度词条的信息 主要参考慕课网的《开发简单爬虫》以及一些数据库操作
开发工具
—工欲善其事 必先利其器
首先 这里开发工具用的Python3.6+Pycharm+MySQL5.7+SQLyog
前面2个的安装直接网上搜下教程一大堆 而且免去了配置环境变量的操作,MySQL数据库(安装教程也一大堆)现在最新版是5.7 它的安装与之前的有点不同
注意到没 安装时多了一个必须选项 安装InnoDB时设置password 然后再填入即可 其它步骤和一般软件没什么区别
然后去搜索引擎下载SQLyog工具(用Pycharm自带的dataBase应该也可以 有兴趣的小伙伴可以去试试 ) 连接数据库
点击连接 出错的可以看看 进入控制面板→管理工具→服务→看MySQL service是否打开 连接好后创建数据库baikeurl 然后建url表
再建立4个栏位 分别是 id urlname urlhref urlcontent
爬虫的架构及具体流程
1.传入目标url后调用URL管理器
2.URL管理器对URL进行具体的判断与检索后传入网页下载器
3.网页下载器工作后将网页传入网页解析器
4.将解析后的内容(url,title,content等)传入输出器
5.最后输出器进行数据操作(写入文件 导入数据库等)
整个过程采用了严格的面向对象思想 每一过程具体的函数都封装在相应文件中
实例分析
要爬取的链接:http://baike.baidu.com/item/Python
通过浏览器的开发者工具分析可知 百度百科的词条
链接:/item/……的形式
1
| 标题: <dd class="lemmaWgt-lemmaTitle-title"><h1>……</h1> 内容:<div class="lemma-summary">……</div>
|
废话不多说 直接上代码 关键地方带注释 一个包括5个文件
爬虫调度端(主页)
spider.py文件
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
| import html_downloader import html_outputer import html_parser import url_manager class SpiderMain(object): def __init__(self): self.urls = url_manager.UrlManager() self.downloader = html_downloader.HtmlDownloader() self.parser = html_parser.HtmlParser() self.outputer = html_outputer.HtmlOutputer() 抓取过程函数 def craw(self, root_url): count = 1 self.urls.add_new_url(root_url) while self.urls.has_new_url(): try: new_url = self.urls.get_new_url() print('craw %d : %s' % (count, new_url)) html_cont = self.downloader.download(new_url) new_urls, new_data = self.parser.parse(new_url, html_cont) self.urls.add_new_urls(new_urls) self.outputer.collect_data(new_data) if count == 1000: break count = count+1 except: print('craw failed') self.outputer.into_mysql() if __name__ == '__main__': rooturl = 'http://baike.baidu.com/item/Python' obj_spider = SpiderMain() obj_spider.craw(rooturl)
|
url管理器
url_manager.py文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class UrlManager(object): def __init__(self): self.new_urls = set() self.old_urls = set() def add_new_url(self, root_url): if root_url is None: return if root_url not in self.new_urls and root_url not in self.old_urls: self.new_urls.add(root_url) def has_new_url(self): return len(self.new_urls) != 0 def get_new_url(self): new_url = self.new_urls.pop() self.old_urls.add(new_url) return new_url def add_new_urls(self, new_urls): if new_urls is None or len(new_urls) == 0: return for url in new_urls: self.add_new_url(url)
|
网页下载器
html_downloader.py文件
1 2 3 4 5 6 7 8 9
| import urllib.request class HtmlDownloader(object): def download(self, new_url): if new_url is None: return None response = urllib.request.urlopen(new_url) if response.getcode() != 200: return None return response.read()
|
网页解析器
html_parse.py文件
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
| import re import urllib from urllib import parse from bs4 import BeautifulSoup class HtmlParser(object): def parse(self, new_url, html_cont): if new_url is None or html_cont is None: return soup = BeautifulSoup(html_cont,'html.parser' ) new_urls = self._get_new_urls(new_url,soup) new_data = self._get_new_data(new_url,soup) return new_urls,new_data def _get_new_urls(self, new_url, soup): new_urls = set() 获取要爬取的链接 links = soup.find_all('a',href=re.compile(r'/item/\w+')) for link in links: new_url1 = link['href'] new_full_url = parse.urljoin(new_url, new_url1) new_urls.add(new_full_url) return new_urls def _get_new_data(self, new_url, soup): res_data = {} res_data['url'] = new_url title_node = soup.find('dd',class_='lemmaWgt-lemmaTitle-title').find('h1') res_data['title'] = title_node.get_text() summary_node = soup.find('div',class_='lemma-summary') res_data['summary'] = summary_node.get_text() return res_data
|
输出器
html_outputer.py文件
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
| class HtmlOutputer(object): def __init__(self): self.datas = [] def collect_data(self, new_data): if new_data is None: return print(new_data['summary']) self.datas.append(new_data) 数据库操作函数 def into_mysql(self): i = 0 for data in self.datas: conn = pymysql.Connect( host='127.0.0.1', user='你的用户名', password='你的密码', db='数据库名称', port=3306, charset='utf8mb4' ) try: cursor = conn.cursor() i += 1 sql = 'insert into `urls`(`id`,`urlname`,`urlhref`,`urlcontent`)values(%s,%s,%s,%s)' 执行上面的sql语句 并传入4个参数 分别是id,title,url,content cursor.execute(sql, (i, data['title'],data['url'],data['summary'])) conn.commit() finally: conn.close()
|
注:关于编码问题 因为该网页就是采用的utf-8编码 所以无需调用encode()方法编码 直接data[‘summary’]的内容就是正常显示 若将数据写入文件 则需要第二个参数传入encoding=’’ 指定文件编码方式 测试时尽量不用Windows系统自带的IE浏览器 由于默认编码问题 会导致显示乱码(当时就是被这个问题困扰) 换用记事本或其它浏览器就正常显示了
最后点击运行
运行 爬取网页正常 然后我们去看看数据库
数据库也导入成功了 到此 我们的需求就完成了 最后附上github地址