0%

python爬虫实例之用xpath提取段子

爬什么

把百思不得姐网站的所有段子爬取下来,并保存到本地。本来是要爬内涵段子的,可惜访问不到这个网站了。

怎么做

爬虫基本思路:

  • 获取url序列
  • 遍历url序列
    • 提取数据
    • 保存数据

获取url序列

首先进入网站,寻找url的规律。最后发现每一页内容对应的url都是有规律的:(现在找到了url规律,可获取url序列)

1
2
3
4
5
6
第1页:http://www.budejie.com/1
第2页:http://www.budejie.com/2
第3页:http://www.budejie.com/3
……
第50页:http://www.budejie.com/50
总共就50页内容

提取数据

寻找目标数据,发现目标数据在响应的html内容里面,所在位置存在规律。于是使用xpath提取数据,这种方式最简单。
image.png

保存数据

用追加的方式写入数据。
with open("duanzi.txt","a",encoding="utf8") as f:

代码

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
import requests
from lxml import etree
from pprint import pprint

class duanzi:
def __init__(self):
self.url_temp = "http://www.budejie.com/{}"
self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}

def get_url_list(self,url_temp):
url_list = []
for i in range(50): #一共有50页内容
url_list.append(self.url_temp.format(i+1))
return url_list

def parse_url(self,url,headers): #发送请求,获取响应
response = requests.get(url,headers=self.headers)
return response.content.decode()

def get_content(self,html_str): #使用xpath提取数据
html_element = etree.HTML(html_str)
content_list = html_element.xpath("//div[@class='j-r-list-c-desc']/a/text()")
return content_list

def run(self): #实现主逻辑
#1. 获取url列表
url_list = self.get_url_list(self.url_temp)
# print(url_list)
#2. 遍历url列表
for url in url_list:
#3. 发送请求,获取响应
html_str = self.parse_url(url,headers=self.headers)
#3. 提取数据
content_list = self.get_content(html_str)
# pprint(content_list)
#4. 保存
with open("duanzi.txt","a",encoding="utf8") as f: #以追加的方式写入文件
f.write(str(content_list)) #将列表强制转换为str类型

if __name__ == '__main__':
my_duanzi = duanzi()
my_duanzi.run()

总结

这是本人第一次独立使用面向对象的方法搞出的代码,还是开心滴~
本来打算把获取的列表构造成字典,然后用json.dumps的方式写入文件保存(这样就可以使抓取结果显示得更美观)。但是现在段位太低,还不知道怎么做。

优化

找到方法格式化保存了,没错,就是使用json.dumps这个方法。不需要把获取的列表转换为字典~因为json.dumps的作用就是可以把python数据类型转换为字符串类型,列表就是一种python数据类型,可以直接使用json.dumps
代码:

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
import requests
from lxml import etree
from pprint import pprint
import json

class duanzi:
def __init__(self):
self.url_temp = "http://www.budejie.com/{}"
self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}

def get_url_list(self,url_temp):
url_list = []
for i in range(50): #一共有50页内容
url_list.append(self.url_temp.format(i+1))
return url_list

def parse_url(self,url,headers): #发送请求,获取响应
response = requests.get(url,headers=self.headers)
return response.content.decode()

def get_content(self,html_str): #使用xpath提取数据
html_element = etree.HTML(html_str)
content_list = html_element.xpath("//div[@class='j-r-list-c-desc']/a/text()")
return content_list

def run(self): #实现主逻辑
#1. 获取url列表
url_list = self.get_url_list(self.url_temp)
# print(url_list)
#2. 遍历url列表
for url in url_list:
#3. 发送请求,获取响应
html_str = self.parse_url(url,headers=self.headers)
#3. 提取数据
content_list = self.get_content(html_str)
# pprint(content_list)
#4. 保存
with open("duanzi.txt","a",encoding="utf8") as f: #以追加的方式写入文件
for content in content_list: #这里优化了,遍历段子内容,依次格式化写入文件并保存
f.write(json.dumps(content,ensure_ascii=False,indent=2)) #嘻嘻嘻,可以使用json.dumps方式格式化写入文件~
f.write("\n") #添加换行符,一个段子就占一行
# f.write(str(content_list)) #将列表强制转换为str类型

if __name__ == '__main__':
my_duanzi = duanzi()
my_duanzi.run()
-------------本文结束感谢您的阅读-------------