博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python3下基于bs4和sqlalchemy的爬虫实现
阅读量:6091 次
发布时间:2019-06-20

本文共 6718 字,大约阅读时间需要 22 分钟。

本文来自网易云社区

作者:王贝

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

上下模块图:

20180929105546528ebf7b-55c9-42d5-b71b-7aca95fdbd2b.png

一目了然,总体上就是这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时再讲。

    
    
    
    
    
百度一下,你就知道
    
        
            
                
                    
                    
                        
 
 
                        
 
                                                           autocomplete=off autofocus>
                                        
                                                                                         name=tj_trhao123 >                
                                                                                >                        href=http://tieba.baidu.com name=tj_trtieba >                

(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 sessionmakerdburl = '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 SessionManagerBase = 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+款云产品! 

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

相关文章:

【推荐】 
【推荐】 
【推荐】 

你可能感兴趣的文章
Java线程:什么是线程
查看>>
mysql5.7 创建一个超级管理员
查看>>
【框架整合】Maven-SpringMVC3.X+Spring3.X+MyBatis3-日志、JSON解析、表关联查询等均已配置好...
查看>>
要想成为高级Java程序员需要具备哪些知识呢?
查看>>
带着问题去学习--Nginx配置解析(一)
查看>>
onix-文件系统
查看>>
java.io.Serializable浅析
查看>>
我的友情链接
查看>>
多线程之线程池任务管理通用模板
查看>>
CSS3让长单词与URL地址自动换行——word-wrap属性
查看>>
CodeForces 580B Kefa and Company
查看>>
开发规范浅谈
查看>>
Spark Streaming揭秘 Day29 深入理解Spark2.x中的Structured Streaming
查看>>
鼠标增强软件StrokeIt使用方法
查看>>
本地连接linux虚拟机的方法
查看>>
某公司面试java试题之【二】,看看吧,说不定就是你将要做的题
查看>>
BABOK - 企业分析(Enterprise Analysis)概要
查看>>
Linux 配置vnc,开启linux远程桌面
查看>>
CentOS6.4关闭触控板
查看>>
React Native 极光推送填坑(ios)
查看>>