案例:使用正则表达式的爬虫
用正则表达式进行对爬取到的全部网页源代码进行筛选。
网站: https://www.cnblogs.com/loaderman/default.html?page=1
打开之后,不难看到里面一个一个灰常有内涵的段子,当你进行翻页的时候,注意url地址的变化:
-
第一页url: https://www.cnblogs.com/loaderman/default.html?page=1
-
第二页url: https://www.cnblogs.com/loaderman/default.html?page=2
-
第三页url: https://www.cnblogs.com/loaderman/default.html?page=3
-
第四页url: https://www.cnblogs.com/loaderman/default.html?page=4
这样我们的url规律找到了,要想爬取所有,只需要修改一个参数即可。 下面我们就开始一步一步将数据爬取下来。
第一步:获取数据
1. 按照我们之前的用法,我们需要写一个加载页面的方法。
这里我们统一定义一个类,将url请求作为一个成员方法处理。
我们创建一个文件,叫spider.py
然后定义一个Spider类,并且添加一个加载页面的成员方法
import urllib2 class Spider: """ 爬虫类 """ def loadPage(self, page): """ @brief 定义一个url请求网页的方法 @param page 需要请求的第几页 @returns 返回的页面html """ url = "https://www.cnblogs.com/loaderman/default.html?page=" + str(page) #User-Agent头 user_agent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0' headers = {'User-Agent': user_agent} req = urllib2.Request(url, headers = headers) response = urllib2.urlopen(req) html = response.read() print html #return html
以上的loadPage的实现体想必大家应该很熟悉了,需要注意定义python类的成员方法需要额外添加一个参数self
.
-
那么loadPage(self, page) 中的page是我们指定去请求第几页。
-
最后通过 print html打印到屏幕上。
-
然后我们写一个main函数见到测试一个loadPage方法
2. 写main函数测试一个loadPage方法
if __name__ == '__main__': print '请按下回车开始' raw_input() #定义一个Spider对象 mySpider = Spider() mySpider.loadpage(1)
-
程序正常执行的话,我们会在屏幕上打印了第一页的全部html代码。 如果html中的中文部分显示的可能是乱码 。
则需要简单的将得到的网页源代码处理一下:
def loadPage(self, page): """ @brief 定义一个url请求网页的方法 @param page 需要请求的第几页 @returns 返回的页面html """ url = "https://www.cnblogs.com/loaderman/default.html?page=" + str(page) #User-Agent头 user_agent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0' headers = {'User-Agent': user_agent} req = urllib2.Request(url, headers = headers) response = urllib2.urlopen(req) html = response.read() gbk_html = html.decode('gbk').encode('utf-8') # print gbk_html return gbk_html
注意 :对于每个网站对中文的编码各自不同,所以html.decode(‘gbk’)的写法并不是通用写法,根据网站的编码而异
-
这样我们再次执行以下mySpider.py ,会发现之前的中文乱码可以正常显示了。
第二步:筛选数据
接下来我们已经得到了整个页面的数据。 但是,很多内容我们并不关心,所以下一步我们需要进行筛选。 如何筛选,就用到了上一节讲述的正则表达式。
- 首先
import re
- 然后, 在我们得到的
gbk_html
中进行筛选匹配。
下一步匹配规则:
打开网页,鼠标点击右键 “ 查看源代码 ” 需要的每个的内容i 描述都是在一个
<div>
标签中,而且每个div
都有一个属性class = "
c_b_p_desc
"
所以,我们只需要匹配到网页中所有
<div class="c_b_p_desc">
到</div>
的数据就可以了。
根据正则表达式,我们可以推算出一个公式是:
<div.*?class="c_b_p_desc">(.*?)<a
-
这个表达式实际上就是匹配到所有
div
中class="
里面的内容(具体可以看正则)c_b_p_desc
-
然后将这个正则应用到代码中,我们会得到以下代码:
def loadPage(self): """ 作用:下载页面 """ print "正在下载数据...." url = "https://www.cnblogs.com/loaderman/default.html?page=" + str(self.page) headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"} request = urllib2.Request(url, headers = headers) response = urllib2.urlopen(request) # 获取每页的HTML源码字符串 html = response.read() #print html # 创建正则表达式规则对象,匹配每页里的内容,re.S 表示匹配全部字符串内容 pattern = re.compile('<div\sclass="c_b_p_desc">(.*?)<a', re.S) # 将正则匹配对象应用到html源码字符串里,返回 content_list = pattern.findall(html) # 调用dealPage() 处理数据里的杂七杂八 self.dealPage(content_list) def dealPage(self, content_list): """ 处理每页 """ for item in content_list: # 将集合里的每个数据按个处理,替换掉无用数据 # item = item.replace("<p>","").replace("</p>", "").replace("<br>", "") #print item.decode("gbk") # 处理完后调用writePage() 将写入文件内 self.writePage(item)
这里需要注意一个是
re.S
是正则表达式中匹配的一个参数。如果 没有re.S 则是 只匹配一行 有没有符合规则的字符串,如果没有则下一行重新匹配。
- 如果 加上re.S 则是将 所有的字符串 将一个整体进行匹配,findall 将所有匹配到的结果封装到一个list中。
- 然后我们写了一个遍历
item_list
的一个方法printOnePage()
。
对于获取的数据可以再次将无用的数据过滤掉,得到我们想要的数据即可
第三步:保存数据
- 将数据存放在文件中。
def writePage(self, item): """ item: 处理后的每条 """ # 写入文件内 print "正在写入数据...." with open("loadermanRe.txt", "a") as f: f.write(item)
第四步:显示数据
-
通过参数的传递对page进行叠加来遍历全部内容。
-
只需要在外层加一些逻辑处理即可。
def startWork(self): """ 控制爬虫运行 """ # 循环执行,直到 self.switch == False while self.switch: # 用户确定爬取的次数 self.loadPage() command = raw_input("如果继续爬取,请按回车(退出输入quit)") if command == "quit": # 如果停止爬取,则输入 quit self.switch = False # 每次循环,page页码自增1 self.page += 1 print "谢谢使用!"
- 最后,完成后查看当前路径下的loadermanRe.txt文件,里面已经有了我们要的数据。
简单的小爬虫已实现!!!
程序整体代码:
#!/usr/bin/env python # -*- coding:utf-8 -*- import urllib2 import re class Spider: def __init__(self): # 初始化起始页位置 self.page = 1 # 爬取开关,如果为True继续爬取 self.switch = True def loadPage(self): """ 作用:下载页面 """ print "正在下载数据...." url = "https://www.cnblogs.com/loaderman/default.html?page=" + str(self.page) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"} request = urllib2.Request(url, headers=headers) response = urllib2.urlopen(request) # 获取每页的HTML源码字符串 html = response.read() # print html # 创建正则表达式规则对象,匹配每页里的内容,re.S 表示匹配全部字符串内容 pattern = re.compile('<div\sclass="c_b_p_desc">(.*?)<a', re.S) # 将正则匹配对象应用到html源码字符串里,返回 content_list = pattern.findall(html) # 调用dealPage() 处理数据里的杂七杂八 self.dealPage(content_list) def dealPage(self, content_list): """ 处理每页的数据 """ for item in content_list: # 将集合里按个处理,替换掉无用数据 # item = item.replace("<p>","").replace("</p>", "").replace("<br>", "") # print item.decode("gbk") # 处理完后调用writePage() 将写入文件内 self.writePage(item) def writePage(self, item): """ item: 处理后的每条 """ # 写入文件内 print "正在写入数据...." with open("loadermanRe.txt", "a") as f: f.write(item) def startWork(self): """ 控制爬虫运行 """ # 循环执行,直到 self.switch == False while self.switch: # 用户确定爬取的次数 self.loadPage() command = raw_input("如果继续爬取,请按回车(退出输入quit)") if command == "quit": # 如果停止爬取,则输入 quit self.switch = False # 每次循环,page页码自增1 self.page += 1 print "谢谢使用!" if __name__ == "__main__": spider = Spider() # spider.loadPage() spider.startWork()
效果:
posted on 2019-11-21 20:03 LoaderMan 阅读(1374) 评论(0) 编辑 收藏 举报