Python爬虫入门(一)-爬取CSDN热门博文

Python爬虫入门(一)-爬取CSDN热门博文

标签(空格分隔): python


因毕业设计需要,所以开始学起了python,大部分都是边写边学,遇到问题就google,所以可能有很多写的不好的地方,有好的意见请指出.不过主要分享的是遇到了自己不熟悉的东西,如何快速解决该问题的流程.


1.目的

写的目的是抓取csdn博客首页的一些文章的标题,连接,作者,摘要信息,如下图,然后存放到自己的数据库中,为了版权问题,所以不抓取内容了,毕业设计使用的时候直接超链接过去.


Paste_Image.png

接下来分析csdn博客的首页http://blog.csdn.net/,打开F12后,可以查看到文章内容是直接在html中返回,并没有单独的数据接口,因此想要获取数据的第一步就是获取该页面内容.那么大概流程就如下清晰了:

Paste_Image.png

2.获取页面内容

csdn博客的首页是根据模板生成的,没有数据对应的接口,所以直接获取页面即可.代码就很简单了
首先建立一个common模块,用于保存一些公共信息,也方便后期加入抓取其他网站文章.
Common.py

# coding=utf-8
# 伪装浏览器请求,不加header的话请求会报403,因为未被识别成浏览器
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'
}

csdn_url = 'http://blog.csdn.net/?page='

接下来发送请求,获取需要解析的页面

    url = Common.csdn_url + str(x+1)
    print('请求的地址为: ' + url)
    req = request.Request(url, headers= Common.headers)
    result = request.urlopen(req).read().decode('utf-8')
    # result即请求到的csdn页面.

3.解析页面

解析就用到了beautifulSoup4库,官网地址:点击进入,针对使用的话属于跟着文档走一遍就够用的库,具体就不在这里阐述,毕竟本文只是想表达一个应对问题的流程.

3.1 模型

首先因为最终要保存到数据库,所以对数据库表要有一个映射,也就是Model层.


class Article:
    '数据库文章类'

    def __init__(self, raw):
        self.id = raw.get('id')
        self.title = raw.get('title')
        self.user_id = raw.get('userId')
        self.summary = raw.get('summary')
        self.html_content = raw.get('htmlContent')
        self.content = raw.get('content')
        self.keyword = raw.get('keyword')
        self.viewcount = 0
        self.likecount = 0
        self.catelog_id = 0 #需要审核时手动指定
        self.is_top = raw.get('isTop')
        self.is_show = raw.get('isShow')
        self.createdate = raw.get('createdate')
        self.modifydate = raw.get('modifydate')
        self.source = raw.get('source')
        self.source_link = raw.get('sourceLink')
        self.source_author = raw.get('sourceAuthor')

    def __hash__(self):
        return hash(self.id)

    def __eq__(self, other):
        return self.id == other.id

分析:
self指的是该类实例对象本身,个人理解为java类中的this,可以直接访问类中的属性.
def __init__(self, raw)相当于Java中的构造函数,执行Article(raw)的话会自动调用该init方法.
def __hash__(self)和def __eq__(self, other),按照流程图该类会用一个set集合存储,目的是自动根据文章id去重,那么就要了解到python中set集合是如何去重的.这一点和Java差不多,hash值决定了桶的位置,eq决定是否重复..

3.2 解析页面内容

解析一般根据页面内容,分析,然后操作dom树拿到自己想要的东西.这里解析后放到一个字典中,字典的基本结构就是键值对.最后再放到set集合中.

def dealwith(result):
    soup = BeautifulSoup(result,'html.parser')
    blogs = soup.find_all('dl',class_='blog_list clearfix')
    # 获取当前页文章
    for blog in blogs:
        article = dict() #创建字典
        article['userId'] = -1 #代表是机器人
        article['isShow'] = 0 #暂时不展示,后台审核
        article['isTop'] = 0 #不置顶
        dt=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        article['createdate'] = dt #创建时间
        article['modifydate'] = dt #更新时间
        article['source'] = 2 #表示来自csdn

        # 解析作者信息
        nickname = blog.dt.contents[2].string
        article['sourceAuthor'] = nickname

        # 解析文章内容
        content = blog.dd
        for child in content.children:
            if re.search("tracking-ad",str(child)):
                sourceLink = child.a['href']
                articleId = sourceLink[sourceLink.rfind('/')+1 : len(sourceLink)]
                article['id'] = '2'+articleId #csdn文章id
                article['sourceLink'] = sourceLink #原文链接
                article['title'] = child.a.string #原文标题
                continue
            if re.search("blog_list_c",str(child)):
                article['summary'] = child.string #原文摘要
                continue
        # 添加到集合中
        articleList.add(ArticleModel.Article(article))

4.持久化到数据库

保存到数据库中使用到了pymysql库,该库的使用可以参考菜鸟教程:点击进入.
如下使用contextlib建立一个上下文管理器mysqlTemplate().具体执行一会再分析
ArticleService.py

import pymysql
import contextlib

host='127.0.0.1'
port=3306
user='root'
passwd='123456'
db='aust'
charset='utf8'

@contextlib.contextmanager
def mysqlTemplate():
    conn = pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=db, charset=charset)
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    try:
        yield cursor
    finally:
        conn.commit()
        cursor.close()
        conn.close()

然后写一个执行方法:

# 保存到数据库,已经有的数据则直接跳过
def saveToDB():
    sql = "REPLACE INTO `article` VALUES (%s,%s, %s, %s, %s,%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
    with ArticleService.mysqlTemplate() as cursor:
        #读取出set集合
        for x in articleList:
            #执行更新操作
            row_count = cursor.execute(sql,
                        (x.id,x.title,x.user_id,x.summary,x.html_content,x.content,x.keyword,x.viewcount,x.likecount,
                         x.catelog_id,x.is_top,x.is_show,x.createdate,x.modifydate,x.source,x.source_link,x.source_author))
            print(row_count)

分析:
首先使用了@contextlib.contextmanager定义了一个上下文管理器mysqlTemplate(),该函数中是获取数据库连接,然后yield cursor,最后再关闭连接,那么该yield cursor就是主要逻辑代码,也就对应着下面的saveToDB()函数.

首先yield会把该函数转变为生成器,那么yield之前的算是一次next()调用,之后的也算是next()调用,那么中间的就是with产生的调用.

整个流程就是先获取到数据库连接,然后执行到了yield,该函数终端,转而执行with里面的函数,with的as获取到了yield的返回值也就是cursor对象,with执行完毕后之前终端的函数继续执行,关闭数据库资源等.

这里的mysql语句使用了replace into **这样的话,已经收集过得文章就不会重复收集到数据库中了.

那么到此我的需求也就实现了,剩下的就是实际中遇到的一些异常,相信google都能解决掉的.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,326评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,228评论 1 304
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,979评论 0 252
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,489评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,894评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,900评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,075评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,803评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,565评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,778评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,255评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,582评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,254评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,151评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,952评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,035评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,839评论 2 277

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,590评论 25 707
  • 其实生活中的我们大都是犹犹豫豫的。 就像,她在等,等日子一天天过去,等对他的期待越来越少,等生活变的更淡。 每天都...
    一个想留住幸运的珊瑚阅读 228评论 0 0
  • 永嘉五年,十二月 入冬了,阿菟的腿伤也好的差不多了,郗子房还寄信给远在终南山跟随杨羲修习道术的方回讨要了生肌去疤的...
    复明的瞎子阅读 446评论 0 0
  • 卧薪尝胆,忍辱负重,是我们学习的目标,我们主要学习他的坚韧不拔之气概。作为一个君王,他能忍受别人忍受不了的痛苦,下...
    深夜笔厨阅读 295评论 0 0
  • 七绝·落红尘 碧水青烟丝雨春, 苍天冷雾落红尘。 请君应念妆难饰, 莫令娇颜愧路人! 任尔风云我自逍: @H...
    任尔风云我自逍阅读 890评论 3 3