爬取一点点语录网
运行环境:Python3
编译软件:Sublime
这次来爬取这个一点点语录网
先来看看这是一个怎样的网页
一点点语录网
工作内容
爬取标题和相应内容,并保存在本地
同样的第一步,确定爬取目标,搞清url
第一页:http://www.yikexun.cn/lizhi/qianming/list_50_1.html
第二页:http://www.yikexun.cn/lizhi/qianming/list_50_2.html
第三页:http://www.yikexun.cn/lizhi/qianming/list_50_3.html
可以清晰地看出,每一页的url构成都很简单,有明显的数字标识可以确定这是第几页。
并且url中的list_50明显的说明了该页有50条内容
设置默认url为
url = 'http://www.yikexun.cn/lizhi/qianming/list_50_'
相比之前爬取贴吧,这个在url设置上更简单,只需要给定起始页和结束页就可以进行爬取
设置请求头
将url的拼接以及发送请求设置为一个函数,方便后面的调用。
此后的爬虫程序都会以此来进行
handle_request(发送响应获得请求) 函数代码:
def handle_request(url,page=None):
if page !=None:
url = url +str(page) +'.html'
headers = {
'User-Agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;',
}
request = urllib.request.Request(url=url,headers=headers)
return request
这里在返回 request 后,需要读取里面的数据
content = urllib.request.urlopen(request).read().decode()
这里由于原页面返回的是bytes类型,需要decode()解码,转换成str类型。
检查网页元素,通过正则匹配待爬取的数据地址
对原网页检查元素
确定标题是在网页的这一层
会发现其他标题地址都是类似如此
所以就用正则匹配的方法来进行
pattern = re.compile(r'<h3><a href="(/lizhi/qianming/\d+\.html)">(.*?)</a></h3>')
lt = pattern.findall(content)
就是要匹配出所有如下的地址
<a href="/lizhi/qianming/20181241081.html">比你优秀的人还在努力——激励自己,不放弃的经典语录</a>
匹配结果如下图所示
返回的lt是一个列表,列表中的元素都是元组,元组中第一个元素就是正则中第一个小括号匹配到的内容,元组中第二个元素就是正则中第二个小括号匹配的内容
遍历得到的 lt,以此得到标题和相对应内容
返回的 lt 如上所说是一个列表,其中有两个元素,一个是链接,另一个是标题内容
('/lizhi/qianming/20181140997.html', '<b>人到死都要怀抱梦想!</b>')
而需要把其中的标题提取出来
title = href_title[-1]
上面这条代码,将 href_title 中的倒数第一个放进 title,也就是第二个元素(文字部分)
for href_title in lt:
a_href = 'http://www.yikexun.cn' +href_title[0]
title = href_title[-1]
text = get_text(a_href)
string = '<h1>%s</h1>%s' % (title,text)
但是这里是得到了标题,并没有返回其具体内容,
所以写了 get_text 来获得标题下的具体内容
通过之前设置好的 handle_request 函数来发送请求获得响应,就不做过多赘述
从之前的标题点进去,检查元素,确定内容的具体地址
同样,通过正则来对内容的路径进行匹配,在这里用了 re.S模式进行匹配
re.S(DOTALL): 点任意匹配模式,改变’.'的行为
不然程序会报错
特别在这里注意的是,爬取内容的时候,网页中可能会有些许图片,在这里用正则将这些图片内容去除掉,得到的是纯文本信息
pat = re.compile(r'<img .*?>')
text = pat.sub(' ',text)
通过上面者两行代码,将所有图片地址转换为空地址,以做到将图片内容去除
get_text 函数代码:
def get_text(a_href):
#调用函数构建请求对象
request = handle_request(a_href)
#发送请求,得到响应
content = urllib.request.urlopen(request).read().decode()
#解析内容 注意路径,最好从原网页中复制!!!
pattern = re.compile(r'<div class="neirong">(.*?)</div>',re.S)
lt = pattern.findall(content)
text = lt[0]
#将图片信息清空
# 注意路径,最好从原网页中复制!!!
pat = re.compile(r'<img .*?>')
text = pat.sub(' ',text)
return text
最后就是将爬取到的内容写进本地html文件
得到的结果就是下图所示
注意事项:
也是我自己犯的错误,在写正则的时候,对于原网页检索元素得到的地址最好从原网页复制,一些很小的符号或者空格之类,都会影响正则的识别,包括之后的xpath也是一样!
最后附上程序所有代码
import urllib.request
import urllib.parse
import re
def handle_request(url,page=None):
if page !=None:
url = url +str(page) +'.html'
headers = {
'User-Agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;',
}
request = urllib.request.Request(url=url,headers=headers)
return request
def get_text(a_href):
#调用函数构建请求对象
request = handle_request(a_href)
#发送请求,得到响应
content = urllib.request.urlopen(request).read().decode()
#解析内容 注意路径,最好从原网页中复制!!!
pattern = re.compile(r'<div class="neirong">(.*?)</div>',re.S)
# pattern = re.compile(r'<div class="neirong">(.*?)</div>')
lt = pattern.findall(content)
text = lt[0]
# print(text)
# exit()
#将图片信息清空
# 注意路径,最好从原网页中复制!!!
pat = re.compile(r'<img .*?>')
text = pat.sub(' ',text)
return text
def parse_content(content):
#正则
pattern = re.compile(r'<h3><a href="(/lizhi/qianming/\d+\.html)">(.*?)</a></h3>')
lt = pattern.findall(content)
# 标题终端输出
# print(lt)
# exit()
#返回的lt是一个列表,列表中的元素都是元组,元组中第一个元素就是正则中第一个小括号匹配到的内容,元组中第二个元素就是正则中第二个小括号匹配的内容
for href_title in lt:
a_href = 'http://www.yikexun.cn' +href_title[0]
title = href_title[-1]
text = get_text(a_href)
string = '<h1>%s</h1>%s' % (title,text)
with open('lizhi.html', 'a',encoding = "utf-8") as fp:
fp.write("<meta charset='utf-8'>")
fp.write(string)
def main():
url = 'http://www.yikexun.cn/lizhi/qianming/list_50_'
start_page = int(input('请输入起始页:'))
end_page = int(input('请输入结束页:'))
for page in range(start_page,end_page +1):
#根据url组合和page生成指定request
request = handle_request(url,page)
content = urllib.request.urlopen(request).read().decode()
parse_content(content)
if __name__ == '__main__':
main()