前言
编写爬虫需要了解正则表达式,网上内容很多,但在爬虫应用中用到最多的正则表达式是
‘(.*?)’
在Python中,使用re、requests这两个库便很容易爬取基本的网页信息,其中:
- re : 用于匹配正则表达式,具体用法可以参考这篇博客
http://www.cnblogs.com/sevenyuan/archive/2010/12/06/1898075.html
爬虫入门只需要使用的函数为findall和search
- requests : 用于访问、获取网页数据(简单一点理解0.0)
爬虫入门例子,先上代码:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import re
import requests
# import sys
# reload(sys)
# sys.setdefaultencoding('utf-8')
url = 'http://www.jikexueyuan.com/course/android/?pageNum=2'
result = requests.get(url)
# text = result.text
text = result.content
title_filed = re.findall('info-h2">(.*?)</h2>',text,re.S)
title_all = re.findall('">(.*?)</a>', "\n".join(title_filed), re.S)
for title in title_all:
print title
抓取URL中的课程名称,效果如下:
正文
首先分析一下正则表达式
'info-h2">(.*?)</h2>'
先查看网站上课程标题对应的源码位置:
再查看网页细节:
使用ctrl+f查找 info-h2 可以查找到24条标题信息。
再看标题对应的源码:
<h2 class="lesson-info-h2"><a href="//www.jikexueyuan.com/course/2531.html" target="_blank" jktag="&posGP=103001&posArea=0002&posOper=2004&aCId=2531&posColumn=2531.1">Android Studio 全方位指南之初识 Android Studio</a></h2>
因此正则表达式'info-h2">(.*?)</h2>'主要是用于提取类似如下格式的内容:
<a href=""...</a>
测试一下这段代码:
title_filed = re.findall('info-h2">(.*?)</h2>',text,re.S)
for each in title_filed:
print each
输出结果为:
可以看到成功抓取了标题链接信息。
最后提取课程标题,一开始我尝试直接提取:
title_filed = re.findall('info-h2">(.*?)</h2>',text,re.S)
title_all = re.findall('">(.*?)</a>', title_filed, re.S)
结果报错了:
查了一下findall的定义,可以发现findall返回值为list类型,而第二个参数要求使用string
def findall(pattern, string, flags=0):
"""Return a list of all non-overlapping matches in the string.
If one or more groups are present in the pattern, return a
list of groups; this will be a list of tuples if the pattern
has more than one group.
Empty matches are included in the result."""
return _compile(pattern, flags).findall(string)
因此需要将list类型转换为string类型,代码更改为:
title_filed = re.findall('info-h2">(.*?)</h2>',text,re.S)
title_all = re.findall('">(.*?)</a>', "\n".join(title_filed), re.S)
最后成功输出。
再简单抓取一下课程图片
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import re
import requests
url = 'http://www.jikexueyuan.com/course/android/?pageNum=2'
result = requests.get(url)
text = result.content
pic_filed = re.findall('class="lessonimg-box"(.*?) class="lessonplay"',text,re.S)
pic_url = re.findall('img src="(.*?)" class', "".join(pic_filed), re.S)
i= 0
# print pic_url
for each in pic_url:
print '正在下载第' + str(i+1) + '张图片'
try:
pic = requests.get(each, timeout=10)
except requests.exceptions.ConnectionError:
print '无法下载该图片'
continue
string = './pictures/'+str(i+1)+'.jpg'
fp = open(string, 'wb') # 保存图片
fp.write(pic.content)
fp.close()
i += 1
ps: 正则表达式书写要先抓主体再抓细节