【41计划打卡-05】python爬虫帮你百度“相关”的内容
往期:
上期讲到了python爬虫的基础,了解到上期的python的基本逻辑和原理,今天讲给出一个关于百度百科的爬虫案例,点击阅读原文可查看到项目代码。该案例同样来自于慕课网的教程:
Python开发简单爬虫:http://www.imooc.com/learn/563
爬取前准备:
下面是百度百科关于Python的介绍。除了介绍,Python里面还存在大量的蓝色链接,这些链接能让你进一步对Python的相关内容有更多了解,因此,可以通过这些链接,我们能爬取更多和Python有关的数据。
然后需要对网页的html进行分析,需要了解html中我们需要爬取那些内容。
html下对Python标题,可以通过class进行查询。
而摘要段落同样可以class这个特性来实现查询(一个题外话,lemma似乎是一种百度使用的框架?)。
至于链接,可以看到其herf有一定的规律和格式,利用正则表达式能匹配到相关的链接,方便进一步查询。
目标:
以Python为例,抓取百度百科与之有关的1000个链接页面的数据,并输出到output.html文件。
目标细化:
实例目标:百度百科Python词条相关词条网页、标题和简介
入口页:
URL格式:
词条网页URL:/view/125370.htm
数据格式
标题:
<dd class='lemmaWgt-lemmaTitle-title'><h1>**</h1></dd>
简介:
<div class='lemma-summary'>***<div>
页面编码:UTF-8
需要的运行环境:
pycharm、Python2.7、BeautifulSoup4、urllib2等
组件的简要说明
主程序
入口程序,用于指导整个爬虫的运行
craw(root_url) 爬取内容
首先需要对相应的变量和其他组件进行初始化,包括URL管理器,html下载器,解析器和输出器。在craw中定义了爬取内容的过程,从定义爬取内容,到运用上述组件进行数据爬取和处理。定义爬取函数之后,即可对开始执行。下面是实现代码:
# coding:utf-8
# spider_main.py: 入口程序,用于指导整个爬虫的运行
# from baike_spider import url_manager, html_downloader, html_parser, html_outputer
import url_manager, html_downloader, html_outputer, html_parser
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(): # 从url池中爬取数据和添加新的url到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.output_html()
if __name__=="__main__": # 主程序
root_url="http://baike.baidu.com/view/21087.htm"
obj_spider=SpiderMain()
obj_spider.craw(root_url)
url管理器 url_manager.py
url管理器,对新旧url进行管理
__init__() 初始化
add_new_url(url) 添加新链接
add_new_urls(urls) 批量添加新链接
has_new_url() 验证该链接是否已在url池中
get_new_url() 获取新链接
定义一个类作为url管理器,首先需要定义初始化函数,后面的函数就涉及对url的各种处理。url管理器需要设置两个集合,一个放新链接,另一个放已经被爬取过的链接。首先需要接受新的链接,存入,还要给出接口,为主程序新的链接进行爬取。对某些链接,可能在接受时已经在集合里面,这时应不再放入,这点需要设置函数实现。
# coding:utf8
# url_manager.py: url管理器,对新旧url进行管理。
class UrlManager(object):
# 初始化
def __init__(self):
self.new_urls=set()
self.old_urls=set()
# 添加新链接
def add_new_url(self,url):
if url is None:
return
if url not in self.new_urls and url not in self.old_urls:
self.new_urls.add(url)
# 批量添加新链接
def add_new_urls(self,urls):
if urls is None or len(urls)== 0:
return
for url in urls:
self.add_new_url(url)
# 验证该链接是否已在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
网页下载器 html_downloader.py
网页下载器,用urllib2进行下载
download(url) urllib2对网页进行下载
这段代码相对简单,即用urllib2进行网页下载。
# coding:utf8
# html_downloader.py: 网页下载器,用urllib2进行下载
import urllib2
class HtmlDownloader(object):
# urllib2对网页进行下载
def download(self,url):
if url is None:
return None
response=urllib2.urlopen(url)
if response.getcode()!=200:
return None
return response.read()
网页解析器 html_parser.py
网页解析器,运用BeautifulSoup进行网页解析
_get_new_urls(page_url,soup) 获取新url
_get_new_data(page_url,soup) 获取新数据,解析链接内容
parse(page_url,html_cont) 规范化数据
网页解析器需要对网页进行解析,首先是获取新的url和新数据,然后对数据进行规范化,同时在新数据中解析找到新的链接方便下一步的爬取。
# coding:utf8
# html_parser.py: url网页解析器,运用BeautifulSoup进行网页解析
from bs4 import BeautifulSoup
import re
import urlparse
class HtmlParser(object):
# 获取新url
def _get_new_urls(self,page_url,soup):
new_urls=set()
# /view/123.html
links=soup.find_all('a',href=re.compile(r"/view/\d+\.htm"))
for link in links:
new_url=link['href']
new_full_url=urlparse.urljoin(page_url,new_url)
new_urls.add(new_full_url)
return new_urls
# 获取新数据,解析链接内容
def _get_new_data(self,page_url,soup):
res_data={}
# url
res_data['url']=page_url
# <dd class="lemmaWgt-lemmaTitle-title"> <h1>Python</h1>
title_node=soup.find('dd',class_="lemmaWgt-lemmaTitle-title").find("h1")
res_data['title']=title_node.get_text()
#<div class="lemma-summary" label-module="lemmaSummary"> <div class="para" label-module="para">
summary_node=soup.find('div',class_='lemma-summary')
res_data['summary']=summary_node.get_text()
return res_data
# 规范化数据
def parse(self,page_url,html_cont):
if page_url is None or html_cont is None:
return
soup=BeautifulSoup(html_cont,'html.parser',from_encoding='utf-8')
new_urls=self._get_new_urls(page_url,soup)
new_data=self._get_new_data(page_url,soup)
return new_urls,new_data
结果输出组件 html_outputer.py
结果输出组件,对爬取的结果进行输出。
__init__() 初始化
collect_data(data) 数据收集
output_html() 结果输出
最后,对爬取得到的数据进行收集和输出。首先获取解析得到的内容,然后放到数据集中,并准备输出。
# coding:utf8
# html_outputer.py: 结果输出器
class HtmlOutputer(object):
# 初始化
def __init__(self):
self.datas=[]
# 数据收集
def collect_data(self,data):
if data is None:
return
self.datas.append(data)
# 结果输出
def output_html(self):
fout=open('output.html','w')
fout.write("<html>")
fout.write("<body>")
fout.write("<table>")
# 补充:需要将ascii转为utf-8
for data in self.datas:
fout.write("<tr>")
fout.write("<td>%s</td>" % data['url'])
fout.write("<td>%s</td>" % data['title'].encode('utf-8'))
fout.write("<td>%s</td>" % data['summary'].encode('utf-8'))
fout.write("</tr>")
fout.write("</table>")
fout.write("</body>")
fout.write("</html>")
fout.close()
运行结果
最后运行spider_main.py,等待若干时间(如果爬取足够多的数据,可能需要半个小时甚至更多,趁这个时间去转转吧)。运行之后能发现你的文件夹里会多一个文件“output.html”,双击打开即可查看到你爬取到的数据。下面我爬取的结果:
结果以表格形式展现(我没有画线框),第一列是信息来源的链接,中间是主题词,右边是关于该词的摘要或是简单描述。通过这些数据能进一步进行研究。
最后强调一点
从这一整个项目可以看到,简单的爬虫需要的基础知识比较广,如python基础以及相关包的使用,还有html语言和结点,另外还需要正则表达式等。有这些基础知识基本就能实现上述内容了。
但是,这只是最简单的爬虫,在对某些网址,还有登录、验证码、Ajax、服务器防爬虫、多线程、分布式等问题,部分网站还有反爬虫保护,我们若需要爬取信息,则还要进一步研究,从某种程度上说,爬虫算是一种黑客行为,哈哈。
QQ:545281848