python简单爬虫(二)
上一篇简单的实现了获取url返回的内容,在这一篇就要第返回的内容进行提取,并将结果保存到html中。
一 、 需求:
抓取主页面:百度百科Python词条 https://baike.baidu.com/item/Python/407313
分析上面的源码格式,便于提取:
- 关键词分析:位于class为lemmaWgt-lemmaTitle-title的dd元素的第一个h1标签内
- 简介分析(位于class为lemma-summary的div的text内容)
- 其他相关联的标签的分析(是a标签,且href以/item/开头)
二、抓取过程流程图:

三、分析:
1. 网页下载器:
1.作用:
将互联网上URL对应的网页以HTML形式下载到本地
常用的本地下载器
1、urllib2 Python官方基础模块
2、requests 第三方包,功能更强大
2.urllib下载网页的三种方法
(1)URL传入urllib2.urlopen(url)方法
import urllib2
#直接请求
response = urllib2.urlopen('http://www.baidu.com') #获取状态码,如果是200表示成功
code = response.getcode() #读取内容
cont = response.read()
(2)添加data、http header
将url、data、header传入urllib.Request方法
然后 URLlib.urlopen(request)
import urllib2 #创建Request对象
request = urllin2.Request(url) #添加数据
request.add_data('a'.'') #添加http的header 将爬虫程序伪装成Mozilla浏览器
request.add_header('User-Agent','Mozilla/5.0') #发送请求获取结果
response = urllib2.urlopen(request)
(3)添加特殊情景的处理器
处理用户登录才能访问的情况,添加Cookie
或者需要代理才能访问 使用ProxyHandler
或者需要使用https请求
2.网页解析器
1.作用:
从网页中提取有价值数据的工具
以HTML网页字符串为输入信息,输出有价值的数据和新的待爬取url列表
网页解析器种类
1、正则表达式 将下载好的HTML字符串用正则表达式匹配解析,适用于简单的网页解析 字符串形式的模糊匹配
2、html.parser python自带模块
3、BeautifulSoup 第三方插件
4、xml 第三方插件
原理是解析成DOM树:
2.BeautifulSoup简介及使用方法:
1.简介:
BeautifulSoup:Python第三方库,用于从HTML或XML中提取数据
安装并测试beautifulsoup
方法1:-安装:pip install beautifulsoup4
-测试:import bs4
方法2:pycharm--File--settings--Project Interpreter--添加beautifulsoup4
2.语法介绍:
根据HTML网页字符串可以创建BeautifulSoup对象,创建好之后已经加载完DOM树
即可进行节点搜索:find_all、find。搜索出所有/第一个满足要求的节点(可按照节点名称、属性、文字进行搜索)
得到节点之后可以访问节点名称、属性、文字
如:
<a href="123.html" class="aaa">Python</a>
可根据:
节点名称:a
节点属性:href="123.html" class="aaa"
节点内容:Python
创建BeautifulSoup对象:
from bs4 import BeautifulSoup
#根据下载好的HTML网页字符串创建BeautifulSoup对象
soup = BeautifulSoup(
html_doc, #HTML文档字符串
'html.parser' #HTML解析器
from_encoding='utf-8' #HTML文档编码
)
搜索节点:
方法:find_all(name,attrs,string)
#查找所有标签为a的节点
soup.find_all('a')
#查找所有标签为a,链接符合/view/123.html形式的节点
soup.find_all('a',href='/view/123.html')
soup.find('a',href=re.compile('aaa')) #用正则表达式匹配内容
#查找所有标签为div,class为abc,文字为Python的节点
soup.find_all('div',class_='abc',string='Python') #class是Python关键字 避免冲突
由于class是python的关键字,所以讲class属性加了个下划线。
访问节点信息:
得到节点:<a href="123.html" class="aaa">Python</a>
#获取查找到的节点的标签名称
node.name
#获取查找到的节点的href属性
node['href']
#获取查找到的节点的连接文字
node.gettext()
四、代码实现:
spider.py
# 爬虫的入口调度器
from baike import url_manager, html_downloader, html_parser, html_outputer class SpiderMain(object):
def __init__(self):
self.urlManager = url_manager.UrlManager()
self.downloader = html_downloader.HtmlDownLoader()
self.parser = html_parser.HtmpParser()
self.outputer = html_outputer.HtmlOutpter() def craw(self,url):
count = 1 #定义爬取几个页面
self.urlManager.add_new_url(url)
while self.urlManager.has_new_url():
try:
# 获取一个url
new_url = self.urlManager.get_new_url()
# 访问url,获取网站返回数据
html_content = self.downloader.download(new_url)
new_urls, new_datas = self.parser.parse(new_url, html_content)
self.urlManager.add_new_urls(new_urls)
self.outputer.collect_data(new_datas)
print(count)
if count == 5:
break
count = count+1
except Exception as e:
print("发生错误",e)
# 将爬取结果输出到html
self.outputer.out_html() if __name__=="__main__":
url = 'https://baike.baidu.com/item/Python/407313'
sm = SpiderMain()
sm.craw(url)
url_manager.py
# url管理器
class UrlManager(object):
def __init__(self):
# 定义两个set,一个存放未爬取的url,一个爬取已经访问过的url
self.new_urls = set()
self.old_urls = set() # 添加一个url的方法
def add_new_url(self,url):
if url is None:
return None
if url not in self.new_urls and url not in self.old_urls:
self.new_urls.add(url) # 判断是否还有待爬取的url(根据new_urls的长度判断是否有待爬取的页面)
def has_new_url(self):
return len(self.new_urls) != 0 # 定义获取一个新的url的方法
def get_new_url(self):
if len(self.new_urls)>0:
# 从new_urls弹出一个并添加到old_urls中
new_url = self.new_urls.pop()
self.old_urls.add(new_url)
return new_url # 批量添加url的方法
def add_new_urls(self, new_urls):
if new_urls is None:
return
for url in new_urls:
self.add_new_url(url)
html_downloader.py
# 读取网页的类
import urllib.request class HtmlDownLoader(object):
def download(self, url):
if url is None:
return
# 访问url
response = urllib.request.urlopen(url)
# 如果返回的状态码不是200代表异常
if response.getcode() != 200:
return
return response.read()
html_parser.py
# 网页解析器类
import re
import urllib from bs4 import BeautifulSoup class HtmpParser(object):
# 解析读取到的网页的方法
def parse(self, new_url, html_content):
if html_content is None:
return
soup = BeautifulSoup(html_content,'html.parser',from_encoding='utf-8')
new_urls = self.get_new_urls(new_url,soup)
new_datas = self.get_new_datas(new_url,soup)
return new_urls, new_datas # 获取new_urls的方法
def get_new_urls(self, new_url, soup):
new_urls = set()
# 查找网页的a标签,而且href包含/item
links = soup.find_all('a',href=re.compile(r'/item'))
for link in links:
# 获取到a必去哦啊Ian的href属性
url = link['href']
# 合并url。使爬到的路径变为全路径,http://....的格式
new_full_url = urllib.parse.urljoin(new_url,url)
new_urls.add(new_full_url)
return new_urls # 获取new_data的方法
def get_new_datas(self, new_url, soup):
new_datas = {}
# 获取标题内容
title_node = soup.find('dd',class_='lemmaWgt-lemmaTitle-title').find('h1')
new_datas['title'] = title_node.get_text() #获取简介内容
summary_node = soup.find('div',class_='lemma-summary')
new_datas['summary'] = summary_node.get_text() new_datas['url'] = new_url return new_datas
html_outputer.py
class HtmlOutpter(object):
# 构造方法
def __init__(self):
self.datas = [] # 收集数据的方法
def collect_data(self, new_datas):
if new_datas is None:
return
# 如果数据不为空就讲数据添加datas集合中
self.datas.append(new_datas) # 输出爬取到的数据到本地磁盘中
def out_html(self):
if self.datas is None:
return
file = open('C:\\Users\\liqiang\\Desktop\\实习\\python\\pythonCraw\\out.html', 'w', encoding='utf-8')
file.write("<html>")
file.write("<head>")
file.write("<title>爬取结果</title>")
# 设置表格显示边框
file.write(r'''
<style>
table{width:100%;table-layout: fixed;word-break: break-all; word-wrap: break-word;}
table td{border:1px solid black;width:300px}
</style>
''')
file.write("</head>")
file.write("<body>")
file.write("<table cellpadding='0' cellspacing='0'>")
# 遍历datas填充到表格中
for data in self.datas:
file.write("<tr>")
file.write('<td><a href='+str(data['url'])+'>'+str(data['url'])+'</a></td>')
file.write("<td>%s</td>" % data['title'])
file.write("<td>%s</td>" % data['summary'])
file.write("</tr>")
file.write("</table>")
file.write("</body>")
file.write("</html>")
运行spider.py的主函数:(结果会将提取到的结果保存到html中)
总结:
python的类类似于java,继承object
python的返回值return和return None一样(None类似于java的null关键字)
python简单爬虫(二)的更多相关文章
- Python简单爬虫入门二
接着上一次爬虫我们继续研究BeautifulSoup Python简单爬虫入门一 上一次我们爬虫我们已经成功的爬下了网页的源代码,那么这一次我们将继续来写怎么抓去具体想要的元素 首先回顾以下我们Bea ...
- GJM : Python简单爬虫入门(二) [转载]
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...
- Python简单爬虫入门三
我们继续研究BeautifulSoup分类打印输出 Python简单爬虫入门一 Python简单爬虫入门二 前两部主要讲述我们如何用BeautifulSoup怎去抓取网页信息以及获取相应的图片标题等信 ...
- Python 简单爬虫案例
Python 简单爬虫案例 import requests url = "https://www.sogou.com/web" # 封装参数 wd = input('enter a ...
- Python简单爬虫
爬虫简介 自动抓取互联网信息的程序 从一个词条的URL访问到所有相关词条的URL,并提取出有价值的数据 价值:互联网的数据为我所用 简单爬虫架构 实现爬虫,需要从以下几个方面考虑 爬虫调度端:启动爬虫 ...
- python简单爬虫一
简单的说,爬虫的意思就是根据url访问请求,然后对返回的数据进行提取,获取对自己有用的信息.然后我们可以将这些有用的信息保存到数据库或者保存到文件中.如果我们手工一个一个访问提取非常慢,所以我们需要编 ...
- python 简单爬虫(beatifulsoup)
---恢复内容开始--- python爬虫学习从0开始 第一次学习了python语法,迫不及待的来开始python的项目.首先接触了爬虫,是一个简单爬虫.个人感觉python非常简洁,相比起java或 ...
- Python简单爬虫记录
为了避免自己忘了Python的爬虫相关知识和流程,下面简单的记录一下爬虫的基本要求和编程问题!! 简单了解了一下,爬虫的方法很多,我简单的使用了已经做好的库requests来获取网页信息和Beauti ...
- python 简单爬虫diy
简单爬虫直接diy, 复杂的用scrapy import urllib2 import re from bs4 import BeautifulSoap req = urllib2.Request(u ...
随机推荐
- 【Java并发编程】之三:线程挂起、恢复与终止的正确方法
挂起和恢复线程 Thread 的API中包含两个被淘汰的方法,它们用于临时挂起和重启某个线程,这些方法已经被淘汰,因为它们是不安全的,不稳定的.如果在不合适的时候挂起线程(比如,锁定共享资源时), ...
- HttpHelper类及调用
首先列出HttpHelper类 /// <summary> /// Http操作类 /// </summary> public class HttpHelper { priva ...
- String Typing CodeForces - 954B
题意: 给一个字符串,可以复制某一段字符,问最少需要多少步能将其输出,比如abcabcd,先输入abc然后再赋值abc再输入d就只需要5步. 复制的这段字符 必须是从字符串的0位置开始复制的 而且只 ...
- linux系统常见命令以及操作
2.安装xshell,安装完打开,配置回话,输入名称(随便).SSH.主机(打开linux,点击右上角电脑图标system etho进行联网,打开终端输入ifconfig回车,找到inet add地址 ...
- 洛谷 P2530 [SHOI2001]化工厂装箱员 解题报告
P2530 [SHOI2001]化工厂装箱员 题目描述 118号工厂是世界唯一秘密提炼锎的化工厂,由于提炼锎的难度非常高,技术不是十分完善,所以工厂生产的锎成品可能会有3种不同的纯度,A:100%,B ...
- CF 566A Matching Names
CF 566A Matching Names 题目描述 给出n个名字和n个昵称,求一个名字和昵称的劈配方案,使得被劈配的名字和昵称的最长公共前缀长度的和最大. 1<=n<=100000 字 ...
- bzoj3007: 拯救小云公主(二分+并查集)
挺水的题...好多题解说是对偶图,其实感觉不能算严格意义上的对偶图吧QAQ 先二分答案r,然后以boss为中心半径为r的圆不能走,求能否从左下走到右上. 不能从左下走到右上,说明这堆圆把图隔开了,于是 ...
- 【bzoj4940】这是我自己的发明
Portal --> bzoj4940 Solution (原题这题面到底是..怎么回事啊深深的套路qwq) 感觉自己对根号的算法还是很..没有感觉啊== 实际上这题和bzoj5016没有任何区 ...
- 【DP】【CF855C】 Helga Hufflepuff's Cup
Description 给你一个树,可以染 \(m\) 个颜色,定义一个特殊颜色 \(k\) , 要求保证整棵树上特殊颜色的个数不超过 \(x\) 个.同时,如果一个节点是特殊颜色,那么它的相邻节点的 ...
- oracle 数据库记录
/*----------------------------------------------------------------------------*/ 问题1[--------] Selec ...