Python爬虫学习(二)

回顾

  上一次我们编写了一个最简单的勉强称的上爬虫的代码,基本上什么事情都没做,只是简单的获取了百度的首页内容,离我们想要的真正爬虫还差远了,今天我们就来进阶一下吧,把获取回来的网页内容进行解析,获取自己想要内容,开始吧,骚年!
  

如何解析网页内容

通过字符串直接解析

  我们知道通过urllib2获取回来的网页内容是字符串,那我们就可以直接使用Python里面字符串的api进行拆分,解析,来获取我们想要的内容,虽然这种方式效率比较低下,但也不失为一种方式,不过我们今天不讲这种方法,我们来讲正则表达式。

通过正则表达式

  何为正则表达式呢?大百度的解释是:

正则表达式,又称正规表示法、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

今天我们讲解的重点内容也不是如何编写正则表达式来匹配我们想要的内容,网络上已经有很多讲解如何编写正则表达式了,如果大家想了解的,可以直接查看该链接,解释的很清楚了,我这边就不啰嗦了,我倡导拿来主义,直接上手项目来学习正则表达式,边做项目边学,开搞吧!

获取淘宝MM的照片和资料

  都说程序猿无妹子,那么今天我们就来获取一些妹子的资料,嘿嘿!
  

获取淘宝MM网站内容

taobaoMM.py

1
2
3
4
5
6
7
8
9
10
11
12
13
#-*-coding:utf-8-*-
import urllib2 #引入python自带的urllib2库

def fetchWebPage(url):
request = urllib2.Request(url)
#伪造UA
request.add_header('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36')
response = urllib2.urlopen(request)
details = response.read().decode("gbk").encode("utf-8") #gbk转换为utf-8
return details; #返回结果

htmlContent = fetchWebPage("http://mm.taobao.com/search_tstar_model.htm")
print htmlContent

查看网页源码,找到自己感兴趣的内容

  打开淘宝MM的链接,通过Chrome开发者工具我们会看到如下内容:
  
接下来我们再深入进去查看淘宝MM所在的标签,最后我们定位到下面这个标签

好了,前期准备工作结束,下面开始具体的解析编码阶段,想想还有点小激动呢!

解析内容

  原以为通过以上的taobaoMM.py代码可以获取到网页的所有内容,可惜的是淘宝MM所在标签是通过动态从服务器后台获取的,使用上面的代码获取出来的结果如下:
  
看到没有,淘宝MM所在的标签竟然是空的,它竟是空的!这叫我如何是好啊,不过不用担心,我们还有Chrome开发利器,通过它我们来看看这些是如何从后台获取到数据进行填充的。
最后查看到的请求如下:


其实它是发出了一个post请求,请求的url为http://mm.taobao.com/tstar/search/tstar_model.do?_input_charset=utf-8,post的数据为

这下我们就更简单了,直接发个post请求,带上需要填充的数据,对返回的json直接解析就好了,开工吧!
taobaoMM.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#-*-coding:utf-8-*-
import urllib2 #引入python自带的urllib2库
import urllib #引入python自带的urllib库
import json #解析json使用
import os

url = 'http://mm.taobao.com/tstar/search/tstar_model.do?_input_charset=utf-8'

def fetchWebPage(url):
request = urllib2.Request(url)
#伪造UA
request.add_header('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36')
response = urllib2.urlopen(request)
details = response.read().decode("gbk").encode("utf-8") #gbk转换为utf-8
return details; #返回结果

def postRequest(url,values):
data = urllib.urlencode(values)
request = urllib2.Request(url,data)
response = urllib2.urlopen(request)
json = response.read().decode("gbk").encode("utf-8") #gbk转换为utf-8
return json; #返回结果

def saveImage(imageURL,fileName):
response = urllib2.urlopen(imageURL)
imageData = response.read()
f = open(fileName,'wb')
f.write(imageData)
f.close()

def mkdir(path):
path = path.strip()
isExist = os.path.exists(path)
if not isExist:
os.mkdir(path)
return True
else:
return False

# htmlContent = fetchWebPage("http://mm.taobao.com/search_tstar_model.htm")
values = {'viewFlag':'A','sortType':'default','currentPage':'1','pageSize':'100'}
jsonData = postRequest(url,values)
jsonDic = json.loads(jsonData)
contentList = jsonDic['data']['searchDOList'];
# count = count(jsonDic['data']['searchDOList'])
# mkdir("Images")
for item in contentList:
# mkdir(item['realName'])
filePath = "Images" + "/" + item['realName'];
mkdir(filePath)
fileName = filePath + "/avatar.jpg";
saveImage(item['avatarUrl'],fileName)

这样我们就可以获取到淘宝MM的封面图了,接下来我们再来获取单个淘宝MM详情页的图片,这个时候就需要用到正则表达式来匹配内容了,首先先通过Chrome开发者工具来查看详情页的标签,定位到想要获取图片的标签,如图所示:

最后定位的标签格式大致如此
<img style="float: none;margin: 10.0px;" src="http://img03.taobaocdn.com/imgextra/i3/745790526/T2qKS4XAxaXXXXXXXX_!!745790526.jpg">
src后面就是我们想要的图片了,编写的获取图片代码如下:

1
2
3
4
5
6
def detailImages(url):
print url
content = fetchWebPage(url)
pattern = re.compile('<img style="float: none;margin: 10.0px;" src="(.*?)"/>') #正则匹配
items = re.findall(pattern,content);
return items;

大功告成了!不过这边有个问题,就是淘宝MM的详情页有防盗刷的机制,好像多请求几次后会要求用户登录,这个问题我们下次讲模拟登录的时候再来处理,我这次为了防止登录所以只采集了一个页面的图片数据,还不会要求我登录。

存起来,慢慢欣赏

最后保存的结果如下:

这样我们就拿到了封面图和详情页面的所有图片了。

后记

  这次本以为需要用到正则来处理网页的结果,可惜爬取回来的网页竟然不包含动态的内容,所以只能另外寻找方法,最后却直接找到api来直接显示结果,发个post请求直接返回json,也算是很方便了,代码也已上传到Github上了,大家可以直接从这里下载。