用python3进行爬取百度百科页面数据实战演练


目录

  1. 什么是爬虫?
  2. Python3简单爬虫架构
    1. url管理器
    2. 网页下载器和urllib.request模块
    3. 网页解析器和BeautifulSoup模块
  3. 用Python3爬取百度百科页面数据实战演练

什么是爬虫?

互联网是由一个一个url相互关联而成的。现在我们需要获得互联网上的信息,我们就需要爬虫。
爬虫就是一段自动抓取互联网信息的程序。爬虫通过其中一个url作为入口,然后访问与之相关联的url并且从每个页面中提取有价值的数据。


Python3简单爬虫架构

爬虫调度器 ——>URL管理器——>网页下载器——>网页解析器——>提取有价值数据


URL管理器

  1. 什么是URL管理器?
    主要管理待抓取URL集合以及已抓取URL集合,防止重复抓取,以及循环抓取。
  2. URL管理器有什么作用(功能)?
    一方面,添加新的URL到待爬取URL集合中,并同时判断待添加的URL是否在待爬取的URL集合中。
    另一方面,获取待爬取的URL,并判断待爬取的集合中是否有URL,再把URL从待爬取集合移到已爬取集合。
  3. URL管理器有什么实现方式?
    1. 内存。使用Python内存,待爬取URL集合和已爬取URL集合都是用set()集合。为什么选用set()集合?因为set()集合有自动去除重复数据的功能。
    2. 关系数据库。我们可以使用Mysql。通过建立数据库进行URL是否被爬取的管理。
    3. 缓存数据库。我们可以使用redis。待爬取URL集合和已爬取URL集合都使用set集合。

网页下载器和urllib.request模块

  1. 什么是网页下载器?
    将互联网上URL对应的网页下载到本地的工具。
  2. 网页下载器的作用?
    网页下载器通过URL连接互联网,然后互联网将HTML页面传给网页下载器,网页下载器将页面信息保存在本地内存或者内存字符串。
  3. 网页下载器的种类

    1. 使用urllib.request模块中的urlopen()方法。

    2. 通过添加特殊情景的处理器。
      有四种特殊情景:HTTPCookieProcessor(需要用户登录才能访问)、ProxyHandler(需要代理才能访问)、HTTPSHandler(协议使用HTTPS加密访问)、HttpRedirectHandler(URL实现自动跳转)
      都需要采用urllib.request.build_opener()和urllib.request.install_opener()方法进行opener的创建和安装。
      opener = urllib.request.build_opener(handler)
      urllib.request.install_opener(opener)
      response = urllib.request.urlopen(“https://www.baidu.com“)

#使用urllib.request模块中的urlopen()方法


import urllib.request 

#直接请求       response=urllib.request.urlopen("http://www.baidu.com")

#获取状态码,如果是200,则表示获取成功
print (response.getcode())

#读取内容
print (response.read())
#通过添加特殊情景的处理器。

#导入相应的模块
import urllib.request
import http.cookiejar

#创建HTTPCookieProcessor

cj = http.cookiejar.CookieJar()
pro = urllib.request.HTTPCookieProcessor(cj)

#对opener的创建和安装
opener = urllib.request.build_opener(pro)
urllib.request.install_opener(opener)

#直接请求
response = urllib.request.urlopen('http://www.baidu.com')

#获取状态码,如果是200,则表示获取成功
print (response.getcode())

#读取内容
print (response.read())

网页解析器和BeautifulSoup模块

  1. 什么是网页解析器?
    网页解析器是能从网页提取有价值数据的工具。
  2. 网页解析器的功能?
    网页解析器解析已经下载到本地的HTML网页字符串,然后提取有价值的数据和新的URL列表。

  3. 网页解析器的种类?
    正则表达式——模糊匹配
    html.parser——结构化解析
    BeautifulSoup——结构化解析
    lxml——结构化解析
    其中BeautifulSoup这个插件包含html.parser和lxml,再加上BeautifulSoup这个插件强大,一般我们选用这个插件。 具体的安装过程见Windows和Linux下安装BeautifulSoup

  4. 结构化解析——DOM(Document Object Model)树,具体见DOM解析树

  5. BeautifulSoup的用法,详细见BeautifulSoup详细用法
    如果想具体了解BeautifulSoup用法则可以见BeautifulSoup官方文档

  6. BeautifulSoup的测试

    采用下列测试代码:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# coding:utf-8
import re
from bs4 import BeautifulSoup

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""
#创建beautifulsoup对象
print('创建beautifulsoup对象')
soup = BeautifulSoup(html_doc,'html.parser',from_encoding = 'utf-8')
#搜索节点
print('搜索节点')
links = soup.find_all('a')
for link in links:
    print(link.name,link['href'],link.get_text())

#访问节点
print('访问节点')
link_node = soup.find('a',href = 'http://example.com/lacie')
print(link_node.name,link_node['href'],link_node.get_text())

#正则表达式匹配
print('正则表达式匹配')
link_node = soup.find('a',href = re.compile('ill'))
print(link_node.name,link_node['href'],link_node.get_text())

#获取p段落文字
print('获取p段落文字')
p_node = soup.find('p',class_="title")
print(p_node.name,p_node.get_text())

测试结果:

创建beautifulsoup对象
搜索节点
a http://example.com/elsie Elsie
a http://example.com/lacie Lacie
a http://example.com/tillie Tillie
访问节点
a http://example.com/lacie Lacie
正则表达式匹配
a http://example.com/tillie Tillie
获取p段落文字
p The Dormouse's story

用Python3爬取百度百科页面数据实战演练

  1. 爬虫入口程序:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-


import url_manager,html_downloader,html_parser,html_outputer
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()
                html_cont = self.downloader.download(new_url)
                print("craw %d: %s" %(count,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 = "https://baike.baidu.com/item/Python/407313?fr=aladdin"
    obj_spider = SpiderMain()
    obj_spider.craw(root_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)


    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下载器程序:

import urllib.request
class HtmlDownloader(object):

    def download(self,url):
        if url is None:
            return None
        response = urllib.request.urlopen(url)
        if response .getcode() != 200:
            return None

        return response.read()

HTML解析器

from bs4 import BeautifulSoup
import re
import urllib.parse
class HtmlParser(object):
    def _get_new_urls(self,page_url,soup):
        new_urls = set()
        links = soup.find_all('a',href = re.compile(r"/item/\d+\.htm"))
        for link in links:
            new_url = links['href']
            new_full_url = urllib.parse(page_url,new_url)
            new_urls.add(new_full_url)
        return new_urls

    def _get_new_data(self,page_url,soup):
        res_data = {}
        res_data['url'] = page_url
        title_node = soup.find('dd',href = "lemmaWgt-lemmaTitle-title").find('h1')
        res_data['title'] = title_node.get_next()
        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 None
        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输出程序:

class HtmlOutPuter(object):
    def __init__(self):
        self.datas = []

    def collect_data(self):
        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>")
        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>")

运行结果:

craw 1: https://baike.baidu.com/item/Python/407313?fr=aladdin
craw failed

分析:代码本身是没有错误的,原因是因为我的浏览器是被安全保护的,在

 def _get_new_urls(self,page_url,soup):
        new_urls = set()
        **links = soup.find_all('a',href = re.compile(r"/item/\d+\.htm"))**
        for link in links:
            new_url = links['href']
            new_full_url = urllib.parse(page_url,new_url)
            new_urls.add(new_full_url)
        return new_urls

标星号的正则表达式的匹配中,存在匹配问题。因为在我的浏览器中看到的源代码是:

<a target=_blank 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">

/item/后面全是加密了。没有办法匹配。

上述程序如果看不懂,可以参照视频:慕课网:Python开发简单爬虫
附注:视频上的Python是采用Python2的版本编写,跟本文的程序有点不同,本文的程序是采用Python3编写。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值