从 web 的角度来看,网站架构分为前后端分离和前后端不分离,如果是前后端不分离的结构,我们就需要从响应中去匹配我们希望提取的数据。举个例子就是 果壳网的热门问答。
去正则匹配之前比较习惯先把代码跑通,我们可以尝试去构建出这样的结构,把当前的整个网页先打印出来,再去调试
# coding:utf-8
import requests
# “三季人”是古文吗?
class Guoke(object):
def __init__(self):
self.headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
}
self.url = 'https://www.guokr.com/ask/hottest/'
self.file = open('guoke.json', 'w')
pass
def get_data(self, url):
response = requests.get(url, headers=self.headers)
return response.content
def parse_data(self, data):
str_data = data.decode()
print(str_data)
def run(self):
data = self.get_data(self.url)
self.parse_data(data)
def __del__(self):
self.file.close()
if __name__ == "__main__":
guoke = Guoke()
guoke.run()
运行之后,我们可以发现我们已经获取了当前的完整的网页数据。
我们想要匹配的的是 “三季人”是古文吗?
正则的写法:(.+?)
分别匹配链接和标题 其中? 表示非贪婪模式
修改 parse_data 方法,
def parse_data(self, data):
str_data = data.decode()
res_list = re.findall('(.+?)
', str_data)
print(res_list)
这次我们已经提取到当前页的所有问答的 url 和标题
[('https://www.guokr.com/question/667020/', '“三季人”是古文吗?'), ('https://www.guokr.com/question/392570/', 'EVA Q的这张海报是银河的哪一段啊?'), ('https://www.guokr.com/question/677147/', '什么决定时间的流逝?物体内动能还是?'), ('https://www.guokr.com/question/582248/', '动漫制作有那些过程?'), ('https://www.guokr.com/question/537650/', '干虾为何有氨气味?'), ('https://www.guokr.com/question/676492/', '宝宝总是喜欢吃辣条怎么办?'), ('https://www.guokr.com/question/599265/', '精神病患者,怎样说服她去看医生?'), ('https://www.guokr.com/question/559078/', '用普通塑料袋装热的食物,比如粥什么的,到底有没有害?'), ('https://www.guokr.com/question/160920/', 'wifi信号会受什么的影响?'), ('https://www.guokr.com/question/492513/', '“死”字里为什么有个七夕?'), ('https://www.guokr.com/question/534950/', '科学青年如何写春联?'), ('https://www.guokr.com/question/516692/', '你认为最丑的公式有哪些?'), ('https://www.guokr.com/question/126413/', '有异地恋成功的吗?你们是怎么熬过来的?'), ('https://www.guokr.com/question/506176/', '你是如何理解创业的?'), ('https://www.guokr.com/question/542184/', '《西游记》里为什么把唐僧描写的那么无能?'), ('https://www.guokr.com/question/203569/', '二战美军的降落伞质检的传说是真的吗?'), ('https://www.guokr.com/question/676930/', '未来的果壳还有可能东山再起吗?'), ('https://www.guokr.com/question/628160/', '青蛙能认识自己生的宝宝嘛?'), ('https://www.guokr.com/question/545625/', '咖啡真的能降低自杀率吗?'), ('https://www.guokr.com/question/669761/', '印度人把男人的生殖器叫林伽,把女人的生殖器叫瑜尼,林伽和瑜尼的交合,便是瑜伽。这是真还是假的')]
修改parse_data方法,将元组中的数据组合为字典,再添加到一个字典列表里面:
def parse_data(self, data):
str_data = data.decode()
print(str_data)
res_list = re.findall('(.+?)
', str_data)
temp_list = []
for res in res_list:
temp_dict = {}
temp_dict["url"] = res[0]
temp_dict["title"] = res[1]
temp_list.append(temp_dict)
print(temp_list)
return temp_list
同时定义出数据的保存方法, save_data
def save_data(self, data_list):
for data in data_list:
str_data = json.dumps(data, ensure_ascii=False) + ',\n'
self.file.write(str_data)
guoke.json 文件
{"title": "“三季人”是古文吗?", "url": "https://www.guokr.com/question/667020/"},
{"title": "EVA Q的这张海报是银河的哪一段啊?", "url": "https://www.guokr.com/question/392570/"},
{"title": "什么决定时间的流逝?物体内动能还是?", "url": "https://www.guokr.com/question/677147/"},
{"title": "动漫制作有那些过程?", "url": "https://www.guokr.com/question/582248/"},
{"title": "干虾为何有氨气味?", "url": "https://www.guokr.com/question/537650/"},
{"title": "宝宝总是喜欢吃辣条怎么办?", "url": "https://www.guokr.com/question/676492/"},
{"title": "精神病患者,怎样说服她去看医生?", "url": "https://www.guokr.com/question/599265/"},
{"title": "用普通塑料袋装热的食物,比如粥什么的,到底有没有害?", "url": "https://www.guokr.com/question/559078/"},
{"title": "wifi信号会受什么的影响?", "url": "https://www.guokr.com/question/160920/"},
{"title": "“死”字里为什么有个七夕?", "url": "https://www.guokr.com/question/492513/"},
{"title": "科学青年如何写春联?", "url": "https://www.guokr.com/question/534950/"},
{"title": "你认为最丑的公式有哪些?", "url": "https://www.guokr.com/question/516692/"},
{"title": "有异地恋成功的吗?你们是怎么熬过来的?", "url": "https://www.guokr.com/question/126413/"},
{"title": "你是如何理解创业的?", "url": "https://www.guokr.com/question/506176/"},
{"title": "《西游记》里为什么把唐僧描写的那么无能?", "url": "https://www.guokr.com/question/542184/"},
{"title": "二战美军的降落伞质检的传说是真的吗?", "url": "https://www.guokr.com/question/203569/"},
{"title": "未来的果壳还有可能东山再起吗?", "url": "https://www.guokr.com/question/676930/"},
{"title": "青蛙能认识自己生的宝宝嘛?", "url": "https://www.guokr.com/question/628160/"},
{"title": "咖啡真的能降低自杀率吗?", "url": "https://www.guokr.com/question/545625/"},
{"title": "印度人把男人的生殖器叫林伽,把女人的生殖器叫瑜尼,林伽和瑜尼的交合,便是瑜伽。这是真还是假的", "url": "https://www.guokr.com/question/669761/"},
貌似 ip 被封了 … 一直504 …
过段时间接着写 …
恢复了,换代理也不行,当时应该正好是是服务器挂了 …
回忆联系1里面,我们实现翻页是去更改 ajax 请求的参数。对于数据和 url 在源码中的形式,思路是找到“下一页”对应的 url 然后再去请求这个 url ,循环上述的过程 …
代码如下 :
# coding:utf-8
import requests
import re
import json
class Guoke(object):
def __init__(self):
self.headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
}
self.proxies = {
'http':"http://183.163.40.223:31773",
}
self.url = 'https://www.guokr.com/ask/hottest/'
self.file = open('guoke.json', 'w')
def get_data(self, url):
response = requests.get(url, proxies=self.proxies, headers=self.headers)
print(response.status_code)
# print(response.content)
return response.content
def parse_data(self, data):
str_data = data.decode()
print(str_data)
res_list = re.findall('(.+?)
', str_data)
temp_list = []
for res in res_list:
temp_dict = {}
temp_dict["url"] = res[0]
temp_dict["title"] = res[1]
temp_list.append(temp_dict)
# 匹配 "下一页" 对应的 url
# 下一页
next_url = re.findall('下一页', str_data)
# print(next_url)
# print(temp_list)
if next_url:
next_url = 'https://www.guokr.com' + next_url[0]
return temp_list, next_url
def save_data(self, data_list):
for data in data_list:
str_data = json.dumps(data, ensure_ascii=False) + ',\n'
self.file.write(str_data)
def run(self):
while True:
data = self.get_data(self.url)
data_list, next_url = self.parse_data(data)
self.save_data(data_list)
self.url = next_url
if not next_url:
break
def __del__(self):
self.file.close()
if __name__ == "__main__":
guoke = Guoke()
guoke.run()
查看json文件一共爬取了 64条数据 … 跟网页上的 4 页 64条数据一致 ….
qq:2564493603
欢迎交流