文档章节

Python开发简单爬虫

dotleo
 dotleo
发布于 2017/09/07 11:22
字数 1720
阅读 21
收藏 2
点赞 0
评论 0

本文在学习慕课网 疯狂的蚂蚁crazyant 的课程后写作,文中截图部分来自于视频,感谢视频作者。大家也可以通过点击这里观看视频学习,老师讲得贼棒!

What's 爬虫

通俗的讲,爬虫就是通过一个URL开始,自动获取数据的“网络机器人”。

简单的爬虫架构

pic

  1. URL管理器记录爬取过的URL和未爬取的URL
  2. 从URL管理器中获取一个未爬取的URL下载网页内容
  3. 解析爬取到的内容,将价值数据存储起来,将爬到的新URL传递给URL管理器存储为未爬取的URL,并从2开始循环执行

URL管理器

存储未爬取的URL和爬取过的URL

作用

  • 防止重复抓取。爬取过后的URL存在已爬取URL集合中,不再去访问
  • 防止循环抓取。如果A网页包含B网页的链接,B网页包含A网页的链接,可能导致无限循环。每次添加URL时,判断未爬取URL集合、已爬取URL集合可以避免

需要实现的功能

  • 可以添加新的URL到未爬取集合中,该功能需要判断新的URL是否在URL管理器容器中
  • 判断是否还有未爬取的URL
  • 获取一个待爬取的URL,该功能需要从未爬取的URL集合中删除该URL,并添加到已爬取的URL集合中

实现方式

  • 使用Python,用两个Set分别表示
  • 使用Mysql等数据库存储
  • 使用Redis等,也可以使用两个Set分别表示

网页下载器

将互联网上URL对应的网页下载到本地的工具,本文介绍Python自带库“urllib2”

"urllib2"使用方法

  1. 最简单的使用方法

    pic

  2. 添加data、http header

    pic

  3. 添加特殊情景的处理器(HTTPCookieProcessor、ProxyHandler、HTTPSHandler、HTTPRedirectHandler)

    以添加HTTPCookieProcessor为例:

    pic

网页解析器

网页解析器是从网页中提取有价值数据的工具。

pic

常见的几种网页解析器

  • 正则表达式:可以模糊匹配网页字符串里中的内容,在比较复杂的数据中非常麻烦
  • html.parser:Python自带的解析器
  • lxml:第三方插件,可以解析html和xml
  • Beautiful:第三方插件,它既可以使用html.parser作为解析器,也可以使用lxml作为解析器,功能比较强大,推荐使用

其中,正则表达式是基于文本的模糊匹配;其他3种方式将网页文档解析为DOM树解析。

pic

Beautiful Soup介绍

官网:https://www.crummy.com/software/BeautifulSoup/

pic

对Beautiful Soup进行操作的一般步骤

  1. 先根据HTML网页字符串创建Beautiful Soup对象。
  2. 获取节点,可以通过节点名称、属性值、文字搜索节点。find_all会搜索所有满足要求的节点,find搜索出满足要求的第一个节点。
  3. 访问节点,获取节点的名称、属性、文字的值。
    pic

函数介绍

  1. 创建Beautiful Soup对象

    pic

  2. 搜索节点(find_all,find)

    pic

  3. 访问节点信息

    pic

爬虫实例

分析

  1. 确定目标

    也就是说:我们需要扒取哪个网站和哪些数据。

    本实例我们确定要抓取百度百科“python”词条这个页面和它相关的页面,数据包括页面内的关键词、简介。

  2. 分析目标

    • URL格式,用来限定抓取页面的范围

    本实例抓取的URL是页面中的其他词条的超链接,格式类似于<a 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">计算机程序设计语言</a>

    • 抓取的数据格式,用于存储数据

    本实例都是字符串格式的数据

    • 确定编码,确保程序中的编码格式

    百度百科网页使用utf-8编码,所以在编写代码中注意转码

  3. 编写代码

  4. 执行爬虫

编码

主模块

# -*- coding:utf-8 -*-

import url_manager
import html_downloader
import html_parser
import html_outputer


class SpiderMain(object):

    def __init__(self):
        self.urls = url_manager.UrlManager() # 初始化URL管理器
        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) # 添加url到url管理器
        while self.urls.has_new_url():
            try:
                new_url = self.urls.get_new_url() # 获取未爬过的url
                print 'craw %d : %s' %(count, new_url)
                html_cont = self.downloader.download(new_url) # 根据url下载网页
                new_urls, new_data = self.parser.parse(new_url, html_cont) # 解析网页内容
                self.urls.add_new_urls(new_urls) # 将爬到的新网址添加到url管理器
                self.outputer.collect_data(new_data) # 将内容添加到数据输出器

                if count == 1000:
                    break

                count = count + 1
            except:
                print 'craw failed'


        self.outputer.output_html() # 输出内容

# main函数
if __name__ == '__main__':
    root_url = 'https://baike.baidu.com/item/Python' # 最开始的url
    obj_spider = SpiderMain()
    obj_spider.craw(root_url)

URL管理器

# -*- coding:utf-8 -*-

# URL管理器
class UrlManager(object):

    def __init__(self):
        self.new_urls = set() # 存放未读取url
        self.old_urls = set() # 存放已读取url

    # 添加一个url到未读url列表
    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)

    # 添加多个url到未读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

    # 随机获取一个未读url
    def get_new_url(self):
        new_url = self.new_urls.pop() # 获取未读url并删除
        self.old_urls.add(new_url) # 添加这个url到已读url列表中
        return new_url

网页下载器

# -*- coding:utf-8 -*-

import urllib2

# 网页下载器
class HtmlDownloader(object):

    # 获取服务器响应内容
    def download(self,url):
        if url is None:
            return None

        response = urllib2.urlopen(url)

        if response.getcode() != 200: # 获取成功标识
            return None

        return response.read()

网页解析器

# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
import re

# 网页解析器
class HtmlParser(object):

    # 获取其中的url
    def __get_new_urls(self,page_url, soup):
        new_urls = set()
        links = soup.find_all('a', href=re.compile(r'/item/[a-zA-Z0-9%]+')) # 匹配url,可能会发生变化
        for link in links:
            new_url = link['href'].encode('utf-8') # 获取url
            new_full_url = 'https://baike.baidu.com'+new_url # 拼接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', 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

    # 解析htnl字符串
    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

数据输出器

# -*- coding:utf-8 -*-

# 数据输出器
class HtmlOutputer(object):

    def __init__(self):
        self.datas = list()

    # 添加数据到列表中
    def collect_data(self, data):
        if data is None:
            return
        self.datas.append(data)

    # 输出到html文件中
    def output_html(self):
        fout = open(r'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>')

        fout.close()


文章除注明转载外,均为原创。欢迎任何形式的转载,但请务必注明出处:

文章转载自 OSchina 开源中国
本文作者:dotleo
作者主页:https://my.oschina.net/u/2930289/blog

© 著作权归作者所有

共有 人打赏支持
dotleo
粉丝 10
博文 42
码字总数 48892
作品 0
天津
程序员
5个python爬虫教材,让小白也有爬虫可写,含视频教程!

认识爬虫   网络爬虫,如果互联网是一张蜘蛛网,网络爬虫既是一个在此网上爬行的蜘蛛,爬了多少路程即获取到多少数据。 python写爬虫的优势   其实以上功能很多语言和工具都能做,但是用...

柯西带你学编程 ⋅ 06/12 ⋅ 0

福利 | Python专场竞技,这些书给你加把力!

端午节将至,各地龙舟备战竞技,粽子部队也整装待发。小编掐指一算,这种热闹的时节,是时候展现真正的技(fu)术(li)了! (“Python号”龙舟闪亮登场!) Python作为当下最流行的编程语言...

⋅ 06/15 ⋅ 0

高级爬虫(一):Scrapy爬虫框架的安装

Hi 小伙伴们差不多有半个月没有更新干货了,一直有点忙,而且这中间还有曲折过程,也就没有更新文章. 但今天无论如何也要更新一篇文章,接下来是爬虫高级篇重点讲解的地方! 最近会连载Scrap...

Python绿色通道 ⋅ 04/22 ⋅ 0

不是你学不会Python,只说你的学习方法不对!那如何学习Python呢

有没有那么一个瞬间,你想放弃学习Python? 做任何事情一定有在短期内简单可行的方法。学习不应该是苦差事,而应该是快乐的,重要的是找到适合自己的学习方法。 很多人觉得自己一定能够自学好...

Python燕大侠 ⋅ 06/06 ⋅ 0

想用 Python 找到一份好工作?这4种工作最热门!

身边有不少朋友最近都开始学习python,大多都在学了一两个月之后来问小编,我现在已经入行了,能去找什么样的工作呢? 小编只能说: 入行!=找工作 那么,自学python的人,如何才能找到满意的工...

python达人 ⋅ 05/16 ⋅ 0

高手问答第 202 期 —— 想要玩转 Python?不妨从 Python 网络爬虫开始

OSCHINA 本期高手问答(2018 年 6 月 20 日 — 6 月 26 日)我们邀请到了黄永祥@XyHJw 和大家一起讨论关于 Python 爬虫的问题。 黄永祥,信息管理与信息系统专业学士,曾从事过系统开发和自动化...

局长 ⋅ 06/19 ⋅ 0

学Python有什么用?python入门

  现下Python 可以做任何事情,无论是从入门级选手到专业级选手都在做的爬虫,还是Web 程序开发、桌面程序开发还是科学计算、图像处理,Python都可以胜任。   Python为我们提供了非常完善...

老男孩Linux培训 ⋅ 06/01 ⋅ 0

资深程序员为大家带来30分钟Python 爬虫教程!能看懂就能学会!

图片来源:Blake Connally 发布于Unsplash.com 简单图片爬虫的原料 简单图片爬虫的菜谱 以上的所有都安装好了?棒!在我们继续开始写代码前,我先来解释一下以上这些原料都是用来干什么的。 ...

python达人 ⋅ 05/15 ⋅ 0

为什么Python成了开发AI的主流语言?Java系列、Ruby等编程语言不行吗?

导读 说道开发AI的语言,很多人说,不是Python吗?没错,Python是可以开发AI,但是不知道你们有没有想过,真的就只有Python才可以开发AI吗? 其实,像Java、Ruby也是开发AI很好的选择,但是为...

柯西带你学编程 ⋅ 05/29 ⋅ 0

荐书丨确认过眼神,这份Python书单一定是你的菜

点击上方“程序人生”,选择“置顶公众号” 第一时间关注程序猿(媛)身边的故事 Python 是军刀型的开源工具,被广泛应用于Web 开发、爬虫、数据清洗、自然语言处理、机器学习和人工智能等方...

csdnsevenn ⋅ 05/05 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

vbs 取文件大小 字节

dim namedim fs, s'name = Inputbox("姓名")'msgbox(name)set fs = wscript.createobject("scripting.filesystemobject") 'fs为FSO实例if (fs.folderexists("c:\temp"))......

vga ⋅ 59分钟前 ⋅ 1

高并发之Nginx的限流

首先Nginx的版本号有要求,最低为1.11.5 如果低于这个版本,在Nginx的配置中 upstream web_app { server 到达Ip1:端口 max_conns=10; server 到达Ip2:端口 max_conns=10; } server { listen ...

算法之名 ⋅ 今天 ⋅ 0

Spring | IOC AOP 注解 简单使用

写在前面的话 很久没更新笔记了,有人会抱怨:小冯啊,你是不是在偷懒啊,没有学习了。老哥,真的冤枉:我觉得我自己很菜,还在努力学习呢,正在学习Vue.js做管理系统呢。即便这样,我还是不...

Wenyi_Feng ⋅ 今天 ⋅ 0

博客迁移到 https://www.jianshu.com/u/aa501451a235

博客迁移到 https://www.jianshu.com/u/aa501451a235 本博客不再更新

为为02 ⋅ 今天 ⋅ 0

win10怎么彻底关闭自动更新

win10自带的更新每天都很多,每一次下载都要占用大量网络,而且安装要等得时间也蛮久的。 工具/原料 Win10 方法/步骤 单击左下角开始菜单点击设置图标进入设置界面 在设置窗口中输入“服务”...

阿K1225 ⋅ 今天 ⋅ 0

Elasticsearch 6.3.0 SQL功能使用案例分享

The best elasticsearch highlevel java rest api-----bboss Elasticsearch 6.3.0 官方新推出的SQL检索插件非常不错,本文一个实际案例来介绍其使用方法。 1.代码中的sql检索 @Testpu...

bboss ⋅ 今天 ⋅ 0

informix数据库在linux中的安装以及用java/c/c++访问

一、安装前准备 安装JDK(略) 到IBM官网上下载informix软件:iif.12.10.FC9DE.linux-x86_64.tar放在某个大家都可以访问的目录比如:/mypkg,并解压到该目录下。 我也放到了百度云和天翼云上...

wangxuwei ⋅ 今天 ⋅ 0

PHP语言系统ZBLOG或许无法重现月光博客的闪耀历史[图]

最近在写博客,希望通过自己努力打造一个优秀的教育类主题博客,名动江湖,但是问题来了,现在写博客还有前途吗?面对强大的自媒体站点围剿,还有信心和可能型吗? 至于程序部分,我选择了P...

原创小博客 ⋅ 今天 ⋅ 0

IntelliJ IDEA 2018.1新特性

工欲善其事必先利其器,如果有一款IDE可以让你更高效地专注于开发以及源码阅读,为什么不试一试? 本文转载自:netty技术内幕 3月27日,jetbrains正式发布期待已久的IntelliJ IDEA 2018.1,再...

Romane ⋅ 今天 ⋅ 0

浅谈设计模式之工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻...

佛系程序猿灬 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部