背景
在学习廖雪峰老师的python教程,和优达学城的数据分析课程,了解了python的使用,以及数据清洗和处理的一些方法后,想到了“数据获取”。然后就搜到了一篇讲解Python爬虫的系列教程 http://cuiqingcai.com/1052.html。
把基础只是学习完后,跟着做了两个实战:
1. Python爬虫实战一之爬取糗事百科段子
2. Python爬虫实战二之爬取百度贴吧帖子
练习
这两个网站比较简单,页码可作为参数传过去,没有JS渲染。主要工作就是分析一下网站HTML源代码,然后用正则表达式去匹配一下自己想要的部分即可。
爬取糗事百科段子
正则表达式如下:
# 版本一,输出:作者、文字内容、点赞数、评论数
regex = '<div.*?author.*?<a.*?<h2>(.*?)</h2>.*?<div.*?content.*?<span>(.*?)</span>.*?<span.*?stats-vote.*?><i.*?number.*?>(.*?)</i>(.*?)</span>.*?<span.*?stats-comments.*?<i.*?number.*?>(.*?)</i>(.*?)</a>'
# 版本二,输出:作者、文字内容、图片链接、点赞数、评论数
regex = '<div.*?author.*?<a.*?<h2>(.*?)</h2>.*?<div.*?thumb.*?<img src="(.*?)".*?<div.*?content.*?<span>(.*?)</span>.*?<span.*?stats-vote.*?><i.*?number.*?>(.*?)</i>(.*?)</span>.*?<span.*?stats-comments.*?<i.*?number.*?>(.*?)</i>(.*?)</a>'
测试代码(参考原作者教程):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2017-06-16 11:08:07
# @Author : kk (zwk.patrick@foxmail.com)
# @Link : blog.csdn.net/PatrickZheng
import urllib, urllib2
import re
page = 1
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36'
headers = {'User-Agent': user_agent}
try:
request = urllib2.Request(url, headers = headers)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
# 版本一,输出:作者、文字内容、点赞数、评论数
regex = '<div.*?author.*?<a.*?<h2>(.*?)</h2>.*?<div.*?content.*?<span>(.*?)</span>.*?<span.*?stats-vote.*?><i.*?number.*?>(.*?)</i>(.*?)</span>.*?<span.*?stats-comments.*?<i.*?number.*?>(.*?)</i>(.*?)</a>'
pattern = re.compile(regex ,re.S)
#1).*? 是一个固定的搭配,.和*代表可以匹配任意无限多个字符,加上?表示使用非贪婪模式进行匹配,也就是我们会尽可能短地做匹配,以后我们还会大量用到 .*? 的搭配。
#2)(.*?)代表一个分组,在这个正则表达式中我们匹配了五个分组,在后面的遍历item中,item[0]就代表第一个(.*?)所指代的内容,item[1]就代表第二个(.*?)所指代的内容,以此类推。
#3)re.S 标志代表在匹配时为点任意匹配模式,点 . 也可以代表换行符。
items = re.findall(pattern, content)
for item in items:
great = re.search(u'好笑', item[3])
comment = re.search(u'评论', item[5])
print '作者:', item[0]
print '内容:', item[1]
if great:
print '点赞数:', item[2]
if comment:
print '评论数:', item[4]
print '---------------------------------'
except urllib2.HTTPError, e:
if hasattr(e, 'code'):
print e.code
except urllib2.URLError, e:
if hasattr(e, 'reason'):
print e.reason
爬取百度贴吧帖子
正则表达式如下:
- 提取标题
re.compile('<h3 class="core_title_txt.*?>(.*?)</h3>', re.S)
- 提取总页码
re.compile('<li class="l_reply_num.*?<span class="red">(.*?)</span>', re.S)
- 提取正文
re.compile('<div id="post_content_.*?>(.*?)</div>', re.S)
另外,在设置文件标题时,遇到了编码问题,搜索到相关的解决方法,如下:
def setFileTitle(self, title):
if title is None:
title = self.defaultTitle
# 使用open()时,这样写open(name.decode('utf-8'), 'w'),这样创建的中文文件名就没有乱码问题了
# http://www.cnblogs.com/dragonisnotghost/p/4515581.html
self.file = open((title + '.txt').decode('utf-8'), 'w+')
上述源码放在 Patrick-kk的github,一起学习交流