wsygdb

描述

该链接爬取的是作者在CSDN上写的博文,我就研究爬取一下我自己在博客园上的博文吧。
这是我的博客园首页:http://www.cnblogs.com/wsygdb/default.html

确定要提取的信息:
1.标题
2.发布日期
3.文章链接
4.浏览量
5.评论量

确认headers

使用fiddler来查看访问我的博客园首页所需的报头:

确认报头为:

headers = {
    \'Host\': \'www.cnblogs.com\',
    \'Connection\': \'keep-alive\',
    \'User-Agent\': \'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36\',
    \'Accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\',
    \'Accept-Encoding\': \'gzip, deflate\',
    \'Accept-Language\': \'zh-CN,zh;q=0.9\'
}

分析网页源代码

获取网页源代码

根据url和伪装的header获取网页源代码

def getHtml(url,headers):
    request = urllib.request.Request(url=url,headers=headers)
    page = urllib.request.urlopen(request)
    html = page.read()
    return html

调用时,报错:UnicodeDecodeError: \'utf-8\' codec can\'t decode byte 0x8b in position 1: invalid start byte

我怀疑是不是程序获取的页面源码是经过压缩的,添加解压过程:
解压

def ungzip(data):
    try:
        print(\'正在解压...\')
        data = gzip.decompress(data)
        print(\'解压完成\')
    except:
        print(\'未压缩,无需解压\')
    return data

OK,问题完美解决

提取博文信息

博文需要提取两个信息:

  1. 文章链接、文章标题、发布时间、阅读数和评论数;
  2. “下一页”的链接;

获取文章链接、文章标题、发布时间、阅读数和评论数

如图,这是一篇文章的相关数据:

			<div class="postTitle">
				<a id="homepage1_HomePageDays_DaysList_ctl06_DayList_TitleUrl_0" class="postTitle2" href="http://www.cnblogs.com/wsygdb/p/7661220.html">解决:Invalid character found in the request target.The valid characters are defined in RFC 7230 and RFC3986</a>
			</div>
			<div class="postCon"><div class="c_b_p_desc">摘要: [toc] 背景 在将tomcat升级到7.0.81版后,发现系统的有些功能不能使用了,查询日志发现是有些地址直接被tomcat认为存在不合法字符,返回HTTP 400错误响应,错入信息如下: 原因分析 经了解,这个问题是高版本tomcat中的新特性:就是严格按照 RFC 3986规范进行访问解析,<a href="http://www.cnblogs.com/wsygdb/p/7661220.html" class="c_b_p_desc_readmore">阅读全文</a></div></div>
			<div class="clear"></div>
			<div class="postDesc">posted @ 2017-10-13 14:59 我是一个豆笔 阅读(62) 评论(0)  <a href ="https://i.cnblogs.com/EditPosts.aspx?postid=7661220" rel="nofollow">编辑</a></div>
			<div class="clear"></div>

获取文章的相关信息的正则表达式:文章链接、文章标题、发布时间、阅读数和评论数
articleInfoRe = r\'class="postTitle2".href="(.?)">(.?).?@.(.?).我是一个豆笔.?阅读((.?)).?评论((.?))\'

获取“下一页”的链接

如图,这是“下一页”的页面源代码数据:

<div class="topicListFooter"><div id="nav_next_page"><a href="http://www.cnblogs.com/wsygdb/default.html?page=2">下一页</a></div></div>

对应的正则表达式为:
isNextPage = r\'href="(.*?)">下一页\'

此处对正则表达式做一个简要说明:
1).
? 是一个固定的搭配,.和代表可以匹配任意无限多个字符,加上?表示使用非贪婪模式进行匹配,也就是我们会尽可能短地做匹配,以后我们还会大量用到 .? 的搭配。
2)(.?)代表一个分组,在这个正则表达式中我们匹配了1个分组,在后面的遍历item中,item[0]就代表第一个(.?)所指代的内容,item[1]就代表第二个(.?)所指代的内容,以此类推。

获取我的博客园的所有文章数据

获取规则:
分页获取我的博客园的所有的文章链接、文章标题、发布时间、阅读数和点赞数。
匹配该页是否还有下一页,若有则继续获取下一页的数据,直到最后一页。

这是整个程序代码:

\'\'\'
描述:博客园的文章列表爬虫(http://www.cnblogs.com/wsygdb/default.html),获取每篇文章的标题、发布日期、文章链接、浏览量和评论量。
时间:2017.11.28
作者:我是一个豆笔
\'\'\'

import urllib.request,sys,gzip,re
print(sys.getdefaultencoding())

headers = {
    \'Host\': \'www.cnblogs.com\',
    \'Connection\': \'keep-alive\',
    \'User-Agent\': \'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36\',
    \'Accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\',
    \'Accept-Encoding\': \'gzip, deflate\',
    \'Accept-Language\': \'zh-CN,zh;q=0.9\'
}

# 判断是否还有下一页
isNextPage = r\'href="(.*?)">下一页</a></div></div>\'

# 获取文章的相关信息的正则表达式链接、文章标题、发布时间、阅读数和评论数
articleInfoRe = r\'class="postTitle2".href="(.*?)">(.*?)</a>.*?@.(.*?).我是一个豆笔.*?阅读\((.*?)\).*?评论\((.*?)\)\'

url = \'http://www.cnblogs.com/wsygdb/default.html\'

# 根据url和伪装的header获取网页源代码
def getHtml(url,headers):
    request = urllib.request.Request(url=url,headers=headers)
    page = urllib.request.urlopen(request)
    html = page.read()
    return html

# 解压
def ungzip(data):
    try:
        print(\'正在解压...\')
        data = gzip.decompress(data)
        print(\'解压完成\')
    except:
        print(\'未压缩,无需解压\')
    return data

html = getHtml(url,headers)
data = ungzip(html).decode(\'utf-8\')
# print(data)

allArticleInfo = []

while True:
    # 获取当前页列表
    articleInfoCom = re.compile(articleInfoRe, re.S)  # 由于有换行的情况,使用DOTALL模式匹配
    articleInfos = re.findall(articleInfoCom, data)
    for articleInfo in articleInfos:
        allArticleInfo.append(articleInfo)

    # 按照是否有“下一页”来判断是否获获取完了所有页
    isNextPageCom = re.compile(isNextPage) 
    nextPages = re.findall(isNextPageCom, data)
    if len(nextPages)>=1:
        nextPage = nextPages[0]
        print(nextPage)
        if nextPage != "":
            url = nextPage
            html = getHtml(url, headers)
            data = ungzip(html).decode(\'utf-8\')
            continue
        else:
            break
    else:
        break

# 循环输出
for articleInfo in allArticleInfo:
    print(articleInfo)

分类:

技术点:

相关文章: