描述
该链接爬取的是作者在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,问题完美解决
提取博文信息
博文需要提取两个信息:
- 文章链接、文章标题、发布时间、阅读数和评论数;
- “下一页”的链接;
获取文章链接、文章标题、发布时间、阅读数和评论数
如图,这是一篇文章的相关数据:
<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)