此处以爬取百度百科为例
本文的爬虫组成分为以下几部分
1.调度器(controler)
协调几个模块之间的工作
2.url管理器(urlmanager)
去重,如果url已经被抓取过,就不在访问该url
3.html下载器(htmldownloader)
下载html
4.html解析器(htmlparser )
解析html,解析内容为链接和文档
5.数据输出器(dataoutputer)
对数据进行保存
调度器(controler)
#coding:utf-8
#引入各个模块
import Urlmanager
import Htmldownloader
import Htmlparser
import Dataoutputer
#初始化各个模块
urlmanager=Urlmanager.Urlmanager()
htmldownloader=Htmldownloader.Htmldownloader()
htmlparser=Htmlparser.Htmlparser()
dataoutputer=Dataoutputer.Dataoutputer()
firsturl="https://baike.baidu.com/item/Python/407313?fr=aladdin"
urlmanager.add(firsturl)
count = 1
while 1:
if count >100:
break
try:
url=urlmanager.get()
print str(count)+".spider..."+url
html=htmldownloader.download(url)
data,newurls=htmlparser.parse(html)
urlmanager.addall(newurls)
dataoutputer.output(url,data)
count += 1
except:
print url,"爬取失败"
url管理器(urlmanager)
#coding:utf-8
class Urlmanager:
#set集合,内容无序不重复 需要未爬取和已爬取的url两个集合
newurlset=set()
oldurlset=set()
def add(self,url):
"""将一个url存储到url管理器并去重"""
if url != None and url not in self.oldurlset and url not in self.newurlset:
self.newurlset.add(url)
def addall(self,urllist):
"""将一个url列表储存到url管理器"""
for url in urllist:
self.add(url)
def get(self):
"""从url管理器中获取一个url"""
#pop作用是将一个元素从集合中取出并删除
url=self.newurlset.pop()
self.oldurlset.add(url)
return url
html下载器(htmldownloader)
#coding:utf-8
import urllib
class Htmldownloader:
def download(self,url):
"""根据url,下载html"""
response=urllib.urlopen(url)
html=response.read()
return html
html解析器(htmlparser )
#coding:utf-8
from bs4 import BeautifulSoup
import re
class Htmlparser:
def parse(self,html):
"""
解析两个内容
1.数据 class="lemma-summary"
2.链接 href=/item/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80/7073760
"""
soup = BeautifulSoup(html,"html.parser")
content = soup.find("div",class_="lemma-summary").text
urlList = []
links = soup.find_all("a",href=re.compile("/item/.*"))
for link in links:
urlList.append("https://baike.baidu.com"+link.get("href"))
return content,urlList
数据输出器(dataoutputer)
# coding:utf-8
import io
class Dataoutputer:
def output(self,url,data):
f = io.open("baike.txt","a",encoding="utf-8")
f.write((url+"===>"+data+"\n"))
f.close()
使用:
直接运行调度器
效果: