本文来自网易云社区

作者:王贝

小学生现在都在学python了,作为专业程序员当然不能落下了,所以,快马加鞭,周六周末在家学起了python3,python3的基本语法比较简单,相比于Java开发更加敏捷,python3的基础就不讲了,这里主要讲下我这里的爬虫小程序的实现逻辑吧

上下模块图:

一目了然,总体上就是这5步,涉及到python3的requests,bs4,re,sqlalchemy这四个模块。

(1)requests:

是一个很强大的http客户端库,提供了丰富的api,比如发一个get请求:

with requests.get(url,params={},headers={}) as rsp:
   res.text   #返回值文本内容

发一个入参为json的post请求:

with requests.post(url,json={},headers={}) as rsp:
   res.text #返回值文本内容

等等。

这里值得说一下,为什么用with as,with会先执行__enter__()方法,其返回值就是as,requests里返回值就是rsp,当with as 这一逻辑行执行结束时,就会执行__exit__()方法,requests里__exit__()方法将request close掉了,这就是程序没有显示调用close的原因。下面程序里会有一个例子彰显with as的功能。

requests还有很多强大的功能,参考:https://www.cnblogs.com/lilinwei340/p/6417689.html。

(2)bs4 BeatifulSoup

学过java的都知道java有个jsoup,jsoup就是对html模版进行解析,变成各个标签集合,这里bs4和jsoup如出一辙,api也基本一致,比如,一下html代码,我们想获取新闻,地图,视频,贴吧 这些内容,只要:

soup=BeautifulSoup(html,'html.parser')
atags=soup.find('div',{'id':'u1'}).findChilren('a',{'class':'mnav'})
values=[]for atag in atags:
   values.append(atag.text)

以上程序即可实现我们的要求,python解析html的还有一个scrapy框架的xpath,以后分享scrapy时再讲。

<html>
<head>
    <meta http-equiv=content-type content=text/html;charset=utf-8>
    <meta http-equiv=X-UA-Compatible content=IE=Edge>
    <meta content=always name=referrer>
    <link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css>
    <title>百度一下,你就知道</title></head>
<body link=#0000cc>
<div id=wrapper>
    <div id=head>
        <div >            <div >                <div >                    <div id=lg><img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129></div>
                    <form id=form name=f action=//www.baidu.com/s >                        <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden
                                                                                                          name=rsv_bp
                                                                                                          value=1>
                        <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span
                                ><input id=kw name=wd >                                                           autocomplete=off autofocus></span><span
                                ><input type=submit id=su value=百度一下 ></span></form>
                </div>
            </div>
            <div id=u1><a href=http://news.baidu.com name=tj_trnews >                                                                                         name=tj_trhao123 >                <a href=http://map.baidu.com name=tj_trmap >                                                                                >                        href=http://tieba.baidu.com name=tj_trtieba >                <noscript><a
                        href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1
                        name=tj_login >                <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=' + encodeURIComponent(window.location.href + (window.location.search === "" ? "?" : "&") + "bdorz_come=1") + '" name="tj_login" >登录</a>');</script>
                <a href=//www.baidu.com/more/ name=tj_briicon >        </div>
    </div>
    <div id=ftCon>
        <div id=ftConw><p id=lh><a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a></p>
            <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a>  <a
                    href=http://jianyi.baidu.com/ >                    src=//www.baidu.com/img/gs.gif></p></div>
    </div>
</div>
</body>
</html>

(3) re

re正则模块很强大,有match search sub replace这些api,每个都有自己的特长,可以参考:http://www.runoob.com/python3/python3-reg-expressions.html

(4) sqlalchemy

一款python的数据库orm框架,用了下,很好用,有点类似于java 的hibernate,但更灵活。

说了这么多,该帖下爬虫脚本的代码了,下面是目录结构,毕竟也是专业程序员,不能写的一团糟,也要讲究架构,哈哈。

------youku_any #包名

--------------datasource.py #专门管理数据源session

--------------youkubannerdao.py #程序里抓取的优酷banner信息,这个是dao层

--------------youkuservice.py   #不用说了,业务逻辑

还有一件事情,就是建表,不多说了:

CREATE TABLE `youku_banner` (  `id` bigint(22) NOT NULL AUTO_INCREMENT,  `type` int(2) NOT NULL, #优酷banner类型 1:电视 2:电影 3.综艺 
  `year` int(4) NOT NULL,  `month` int(2) NOT NULL,  `date` int(2) NOT NULL,  `hour` int(2) NOT NULL,  `minute` int(2) NOT NULL,  `img` varchar(255) DEFAULT NULL,  `title` varchar(255) DEFAULT NULL,  `url` varchar(255) DEFAULT NULL,  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  PRIMARY KEY (`id`),  KEY `idx_uniq` (`year`,`month`,`date`,`hour`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=83 DEFAULT CHARSET=utf8mb4

接下来就是代码实现了:

datasource.py

from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmaker

dburl = 'mysql+pymysql://root:123@localhost/youku?charset=utf8'#pool_size 置为100 session回收时间3600sds = create_engine(dburl,pool_size=100,pool_recycle=3600)

Session = sessionmaker(bind=ds)# session=Session()#创建session管理类class SessionManager():

    def __init__(self):
        self.session=Session()    def __enter__(self):
        return self.session    #连接池管理session,不需要显示close
    def __exit__(self, exc_type, exc_val, exc_tb):
        # session.close()
        print('not close')

youkubannerdao.py

from sqlalchemy import Sequence, Column, Integer, BigInteger, String, TIMESTAMP, textfrom sqlalchemy.ext.declarative import declarative_basefrom youku_any.datasource import SessionManager

Base = declarative_base()#继承基类Baseclass YoukuBanner(Base):

    #指定表名
    __tablename__ = 'youku_banner'     #定义字段映射关系
    id = Column(BigInteger, Sequence('id'), primary_key=True)
    type=Column(Integer)
    year = Column(Integer)
    month = Column(Integer)
    date = Column(Integer)
    hour = Column(Integer)
    minute = Column(Integer)
    img = Column(String(255))
    title = Column(String(255))
    url = Column(String(255))
    createTime = Column('create_time', TIMESTAMP)    def add(self):
        #with as 先执行SessionManager __enter__() 逻辑行结束执行__exit()__
        with SessionManager() as session:            try:
                session.add(self)
                session.commit()            except:
                session.rollback()    def addBatch(self,values):
        with SessionManager() as session:            try:
                session.add_all(values)
                session.commit()            except:
                session.rollback()    def select(self,param):
        with SessionManager() as session:            return session.query(YoukuBanner).select_from(YoukuBanner).filter(param)    def remove(self,parma):
        with SessionManager() as session:            try:
                session.query(YoukuBanner).filter(parma).delete(synchronize_session='fetch')
                session.commit()            except:
                session.rollback()    def update(self,param,values):
        with SessionManager() as session:            try:
                session.query(YoukuBanner).filter(param).update(values, synchronize_session='fetch')
                session.commit()            except:
                session.rollback()

youkuservice.py

import requestsimport jsonimport reimport datetimefrom bs4 import BeautifulSoupfrom sqlalchemy import textfrom youku_any.youkubannerdao import YoukuBannerdef getsoup(url):
    with requests.get(url, params=None, headers=None) as req:        if req.encoding != 'utf-8':
            encodings = requests.utils.get_encodings_from_content(req.text)            if encodings:
                encode = encodings[0]            else:
                encode = req.apparent_encoding
        encode_content = req.content.decode(encode).encode('utf-8')
        soup = BeautifulSoup(encode_content, 'html.parser')        return soupdef getbanner(soup):
    # soup = BeautifulSoup()
    # soup.findChild()
    bannerDivP = soup.find('div', {'id': 'm_86804', 'name': 'm_pos'})
    bannerScript = bannerDivP.findChildren('script', {'type': 'text/javascript'})[1].text
    m = re.search('\[.*\]', bannerScript)
    banners = json.loads(m.group())    for banner in banners:
        time = datetime.datetime.now()
        youkubanner = YoukuBanner(type=1, year=time.year, month=time.month, date=time.day, hour=time.hour,
                                  minute=time.minute,
                                  img=banner['img'], title=banner['title'], url=banner['url'])
        youkubanner.add() soup=getsoup('http://tv.youku.com/')
getbanner(soup) youkuBanner = YoukuBanner()
youkuBanner.remove(parma=text('id=67 or id=71'))
youkuBanner.update(param=text('id=70'),values={'title':YoukuBanner.title + '呼啸山庄'})for i in range(0,10000):
    youkuBanner.update(param=text('id=70'), values={'title': YoukuBanner.title + '呼啸山庄'})
    bannerList = youkuBanner.select(param=text('id > 66 and id < 77 order by id asc limit 0,7'))
    print("lines--------%d" % i)    # time.sleep(10)
    for banner in bannerList:
        print(banner.id,banner.minute,banner.img,banner.title)

到此,一个简答的爬虫脚本就写完了,周末两天的成果还是有点小满足,不过这只是python的冰山一脚,还有好多等着我们去探讨呢。

网易云免费体验馆,0成本体验20+款云产品!

更多网易研发、产品、运营经验分享请访问网易云社区

相关文章:
【推荐】 SpringBoot入门(一)——开箱即用

Python3下基于bs4和sqlalchemy的爬虫实现的更多相关文章

  1. 简单的python2.7基于bs4和requests的爬虫

    python的编码问题比较恶心. decode解码encode编码 在文件头设置 # -*- coding: utf-8 -*-让python使用utf8. # -*- coding: utf- -* ...

  2. python3下scrapy爬虫(第二卷:初步抓取网页内容之直接抓取网页)

    上一卷中介绍了安装过程,现在我们开始使用这个神奇的框架 跟很多博主一样我也先选择一个非常好爬取的网站作为最初案例,那么我先用屌丝必备网站http://www.shaimn.com/xinggan/作为 ...

  3. python3制作捧腹网段子页爬虫

    0x01 春节闲着没事(是有多闲),就写了个简单的程序,来爬点笑话看,顺带记录下写程序的过程.第一次接触爬虫是看了这么一个帖子,一个逗逼,爬取煎蛋网上妹子的照片,简直不要太方便.于是乎就自己照猫画虎, ...

  4. 基于Scrapy的B站爬虫

    基于Scrapy的B站爬虫 最近又被叫去做爬虫了,不得不拾起两年前搞的东西. 说起来那时也是突发奇想,想到做一个B站的爬虫,然后用的都是最基本的Python的各种库. 不过确实,实现起来还是有点麻烦的 ...

  5. 基于Node.js的强大爬虫 能直接发布抓取的文章哦

    基于Node.js的强大爬虫 能直接发布抓取的文章哦 基于Node.js的强大爬虫能直接发布抓取的文章哦!本爬虫源码基于WTFPL协议,感兴趣的小伙伴们可以参考一下 一.环境配置 1)搞一台服务器,什 ...

  6. 大数据下基于Tensorflow框架的深度学习示例教程

    近几年,信息时代的快速发展产生了海量数据,诞生了无数前沿的大数据技术与应用.在当今大数据时代的产业界,商业决策日益基于数据的分析作出.当数据膨胀到一定规模时,基于机器学习对海量复杂数据的分析更能产生较 ...

  7. CentOS 环境下基于 Nginx uwsgi 搭建 Django 站点

    因为我的个人网站 restran.net 已经启用,博客园的内容已经不再更新.请访问我的个人网站获取这篇文章的最新内容,CentOS 环境下基于 Nginx uwsgi 搭建 Django 站点 以下 ...

  8. 基于redis的简易分布式爬虫框架

    代码地址如下:http://www.demodashi.com/demo/13338.html 开发环境 Python 3.6 Requests Redis 3.2.100 Pycharm(非必需,但 ...

  9. 基于bs4库的HTML标签遍历方法

    基于bs4库的HTML标签遍历方法 import requests r=requests.get('http://python123.io/ws/demo.html') demo=r.text HTM ...

随机推荐

  1. The first step in solving any problem is recognizing there is one.

    The first step in solving any problem is recognizing there is one.解决问题的第一步是要承认确实存在问题.

  2. 零基础逆向工程19_PE结构03_代码节空白区添加代码_shellcode

    1.获取MessageBox地址,构造ShellCode代码 三种获取方法,参考文章末的一篇帖子. E8 E9计算公式 call 的硬编码:E8 00 00 00 00 jmp 的硬编码:E9 00 ...

  3. iphone开发思维导图

  4. linux python升级及全局环境变量设置

    1.下载pythonwget https://www.python.org/ftp/python/3.4.5/Python-3.4.5.tgz 或者去官网下载压缩包 2.安装python3依赖yum ...

  5. ASUS主板 Type C 接口无效问题

    修改UEFI设置,把 USB TYPE C POWER SWITCH 改成启用

  6. String中关于BeanFactory

    org.springframework.beans及org.springframework.context包是Spring IoC容器的基础.BeanFactory提供的高级配置机制,使得管理任何性质 ...

  7. sql*plus常用指令介紹

    sql*plus常用指令介紹 1.用set指令來設定SQL*Plus的環境參數值 格式: Set 環境參數名 環境參數值 ex:set feedback on set feedback 8.用show ...

  8. skynet 学习笔记-sproto模块(2)

    云风在skynet中继承了sproto的传输协议,对比protobuf的好处是,能明文看到传输内容,而且skynet不需要protobuf这么功能,所以云风也建议在lua层使用sproto来作为sky ...

  9. Android读书笔记四

    第四章 这是一次源代码之旅,学到了如何下载和编译Android源代码和Linux内核源代码.来详细阐述一下一些具体过程 一.Android源代码下载环境 1.安装下载Android源代码的环境配置 ( ...

  10. [bzoj]1930 pacman吃豆豆

    Description 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的路线很奇怪,只能向右走或者向上走,他 ...