如何爬取考研词汇及其反义词例句
参考资料:https://blog.csdn.net/hua_you_qiang/article/details/115224398
思路
- 先找到有考研单词的网站,爬取词汇。爬取网址:http://word.iciba.com/?action=courses&classid=13
- 将爬取的词汇放进单词搜索网站上检索,爬取其近反义词及其例句。网址:http://dict.cn/
- 最终保存到json格式的文件里。
通用步骤
- 导库和头文件设置
- 获取网页源代码
- 进入开发者模式寻找爬取数据的规律
- 保存文件
具体步骤
导库和头文件设置
import requests # HTTP请求
from bs4 import BeautifulSoup # 解析库,从HTML中提取数据
import os # 系统库
import json # json库
from time import sleep #时间库
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
"cookie": "UM_distinctid=1785a4cc9f7303-069f2552a41de7-5771031-144000-1785a4cc9f856b",
"upgrade-insecure-requests": "1"
}
获取网页源代码
爬取网址:http://word.iciba.com/?action=courses&classid=13
# 获取网页源代码
def get_html(url):
try:
r = requests.get(url=url, headers=headers)
r.raise_for_status()
print("text状态:", r.raise_for_status)
r.encoding = r.apparent_encoding
return r.text
except Exception as result:
print("错误原因0:", result)
return ''
- raise_for_status():
这个方法是专门与异常打交道的方法,该方法有这样一个有趣的功能,它能够判断返回的Response类型状态是不是200。如果是200,他将表示返回的内容是正确的,如果不是200,他就会产生一个HttpError的异常。
我们用r.raise_for_status()方法,它就可以有效的判断网络连接的状态。如果网连接出现错误,那么它就会用try-except来获取一个异常。我们在访问或爬取网页过程中,它可能出现的一些错误,或者是网络不稳定造成的一些现象
- r.encoding = r.apparent_encoding:
encoding是从http中的header中的charset字段中提取的编码方式,若header中没有charset字段则默认为ISO-8859-1编码模式,则无法解析中文,这是乱码的原因
apparent_encoding会从网页的内容中分析网页编码的方式,所以apparent_encoding比encoding更加准确。当网页出现乱码时可以把apparent_encoding的编码格式赋值给encoding。
进入开发者模式寻找爬取数据的规律
规律寻找办法:
- 通过url
- 通过html结构中元素的相似性
- 通过http请求返回数据的连接中找到json格式的响应报文(开发者模式中的network)
本例中是使用了第一第二种办法,第三种办法详见:
http://www.moontang.xyz/2021/09/09/%E4%BB%A3%E7%A0%81%E5%9D%97/python/%E5%A6%82%E4%BD%95%E7%88%AC%E5%8F%96%E5%9B%BD%E5%AE%B6%E6%94%BF%E7%AD%96%E7%BD%91%E7%9B%B8%E5%85%B3%E6%95%B0%E6%8D%AE/
本例中,通过规律可以发现:
修改url中的course值可以变换单词列表
所以我们可以通过循环修改course值来查找不同天数的对应单词
for i in range(1, 275):
print(f"正在爬取第{i}个单词网页")
url = f'http://word.iciba.com/action=words&class=13&course={i}'
text = get_html(url)
……
每个单词列表查询html结构会发现单词和翻译都有相似的结构。
![](https://gitee.com/tangxiaoyue107/tmp/raw/master/img/20210928083133.png)
我们可以发现,每个单词和意思都在< li>里,而单词和意思在< li>里的< span>里
所以我们可以写一个get_word函数去获取到span里的信息:
# 获取单词和意思
def get_words(text):# 传入的text是get_html返回的数据
word_dict = dict()# 创建一个字典
soup = BeautifulSoup(text, 'lxml') # 解析库
for each in soup.find_all('li' ): # 找到所有的li标签
span = each.select('span') # 在each中寻找span标签
word_dict[span[0].attrs['title']] = span[1].attrs['title']# 产生一对键值对:键为单词,值为翻译,这两个数据都通过title属性可以找到,所以我们只需要获取不同索引span中的title属性值
return word_dict #返回包含这页所有单词和翻译的字典
爬取完之后我们要将字典中对应的单词放到查词网上去一个个查询它的近义词。
这里采用了两种方法:
- 方案一:先爬取所有的词汇,然后保存。然后将单词从本地取出来放入单词搜索网站上,一个一个爬下来,最后再保存。
- 方案二:爬一页词汇列表,然后将该页词汇列表里的单词放入搜索网站上搜索,爬取后保存。
这两个方法都有利有弊。第一次用的是方案一,因为忘记设置sleep,导致爬取速度过快,被封ip了。所以我这次就用第二种,交替爬取两个网站,再设置sleep,降低访问频率。
爬取单词的近义词及其例句
网址:http://dict.cn/
查找相关网页的规律:
查看url:发现查询的单词和url相关
![](https://gitee.com/tangxiaoyue107/tmp/raw/master/img/20210928085117.png)
查看html网页结构寻找例句
![](https://gitee.com/tangxiaoyue107/tmp/raw/master/img/image-20210928084932631.png)
可以通过这样的代码寻找【例句】:
div = soup.find('div', class_="layout sort")
for li in div.select('li'):
print(li.text)
查看相关单词近反义词(get_word_all函数)(各个单词的近反义词的html结构可能不同):
所以我们需要另外一种方法
比如在< div class=“layout nfo” > 里还有< div >,里面存放的就是【近义词】和【反义词】,那么我们可以通过这个来顺藤摸瓜,直到遇见< ul >节点。然后我们就可以爬到< ul > 节点下的所有< li >子节点(check_word函数)
# 获取近反义词的关键函数
def check_word(tag):
soup = BeautifulSoup(str(tag), 'lxml') #将tag里的数据转换为字符串类型
word_li = [] #因为近反义词不确定是否都有中文翻译,所以我们只用列表存储英文近反义词
for i in soup.find_all('li'):#找到ul下的li
print(i.text.strip()) #apart
if i.text.strip():# 那么str.strip()就是把这个字符串头和尾的空格,以及位于头尾的\n \t之类给删掉。
word_li.append(i.text.strip())
return word_li
def get_word_all(word, translate, search_text):
"""
word: 关键词
translate: word的中文意思
search_text:word的爬虫文本
"""
# 创建一个字典
word_all_dict = dict()
# word_all_dict[word] = {"translate":"",
# "homoionym":{[英文近义单词列表]},
# "antonym":{[英文反义单词列表]},
# "sentence":[英文句子例句]}
word_all_dict[word] = {"translate":translate, "homoionym":list(), "antonym":list(), "sentence":list()}
soup = BeautifulSoup(search_text, 'lxml')
# 获取例句
for each in soup.find('div', class_="layout sort").select('li'):
word_all_dict[word]["sentence"].append(each.text)
# 爬取近反义词
soup = soup.find('div', class_="layout nfo")
for tmp in soup.select('div'):
print(tmp.text) #【近义词】
if "近义词" in tmp.text:
print(tmp) #<div>【近义词】</div>
print(tmp.next) #【近义词】
print('______')
print(tmp.next.next) #/n
print('---------')
print(tmp.next.next.next) # 如下截图
word_all_dict[word]["homoionym"] = check_word(tmp.next.next.next)
if "反义词" in tmp.text:
word_all_dict[word]["antonym"] = check_word(tmp.next.next.next)
return word_all_dict
保存爬取下来的json
# 保存成json格式
def save_word_json(word, word_dict):
path = 'D:/PyCharm 2019.2.6/file/考研'
if not os.path.exists(path): #不存在路径就创建
os.makedirs(path)
print("word_dict",word_dict) #结果如下截图
str_dict = json.dumps(word_dict)#json.dumps将一个Python数据结构转换为JSON
print("str_dict",str_dict) #结果如下截图
fp = open(path+'Words.json', 'a+')
fp.write(str_dict)
fp.write('\n')
fp.close()
print(f"{word}保存成功!")
# 读取加载json文件
def load_json():
path = 'D:/PyCharm 2019.2.6/file/考研/WordPhonetic.json'
with open(path, 'r') as fp:
data = fp.readlines()
for each in data:
word_dict = json.loads(each) #将Json字符串解码成python对象
print(word_dict)
截图:
完整代码
import requests
from bs4 import BeautifulSoup
import os
import enchant
import json
from time import sleep
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
"cookie": "UM_distinctid=1785a4cc9f7303-069f2552a41de7-5771031-144000-1785a4cc9f856b",
"upgrade-insecure-requests": "1"
}
def get_html(url):
try:
r = requests.get(url=url,headers=headers)
r.raise_for_status()
print("text的状态:",r.raise_for_status())
r.encoding = r.apparent_encoding
return r.text
except Exception as result:
print("错误原因:",result)
return ''
# 获取单词和意思
def get_words(text):
word_dict = dict()
soup = BeautifulSoup(text, 'lxml')
for each in soup.find_all('li' ):
span = each.select('span')
word_dict[span[0].attrs['title']] = span[1].attrs['title']
return word_dict
# 获取近反义词的关键函数
def check_word(tag):
soup = BeautifulSoup(str(tag), 'lxml')
word_li = []
for i in soup.find_all('li'):
print(i.text.strip())
if i.text.strip():
print(i.text.strip().split())
# word_li.append(i.text.strip().split())
word_li.append(i.text.strip())
return word_li
def get_word_all(word, translate, search_text):
"""
word: 关键词
translate: word的中文意思
search_text:word的爬虫文本
"""
# 创建一个字典
word_all_dict = dict()
# word_all_dict[word] = {"translate":"",
# "homoionym":{[英文单词列表]},
# "antonym":{[英文单词列表]},
# "sentence":[英文句子中文翻译]}
word_all_dict[word] = {"translate":translate, "homoionym":list(), "antonym":list(), "sentence":list()}
soup = BeautifulSoup(search_text, 'lxml')
# 获取例句
for each in soup.find('div', class_="layout sort").select('li'):
word_all_dict[word]["sentence"].append(each.text)
# 爬取近反义词
soup = soup.find('div', class_="layout nfo")
for tmp in soup.select('div'):
# print(tmp.text)#【近义词】
if "近义词" in tmp.text:
word_all_dict[word]["homoionym"] = check_word(tmp.next.next.next)
if "反义词" in tmp.text:
word_all_dict[word]["antonym"] = check_word(tmp.next.next.next)
return word_all_dict
# 保存成json格式
def save_word_json(word, word_dict):
path = 'D:/PyCharm 2019.2.6/file/考研'
if not os.path.exists(path):
os.makedirs(path)
print("word_dict",word_dict)
str_dict = json.dumps(word_dict)
print("str_dict",str_dict)
fp = open(path+'Words.json', 'a+')
fp.write(str_dict)
fp.write('\n')
fp.close()
print(f"{word}保存成功!")
# 读取加载json文件
def load_json():
path = 'D:/PyCharm 2019.2.6/file/考研/WordPhonetic.json'
with open(path, 'r') as fp:
data = fp.readlines()
for each in data:
word_dict = json.loads(each)
print(word_dict)
def main():
count = 0
for i in range(1, 4):
print(f"正在爬取第{i}个单词网页")
url = f'http://word.iciba.com/?action=words&class=13&course={i}'
text = get_html(url) #先获取html
all_word_dict = get_words(text) #后根据html获取对应英文和意思的字典
# print(all_word_dict)
for word in all_word_dict:
# print(word)
print(f"正在爬取第{count+1}个单词:{word}")
wurl = 'http://dict.cn/'+word
search_text = get_html(wurl) # 获取对应dict网站的关于单词的相关释义
if not search_text: # 如果找不到就跳过
continue
try:
# 获取所有dict网站相关单词的例句,近反义词
word_all = get_word_all(word, all_word_dict[word], search_text)
print(word_all)
# 保存json
save_word_json(word, word_all)
except Exception as result:
print(f"{word}保存失败,错误为:", result)
sleep(2)
count += 1
main()
Beautifulsoup用法大全
相关链接:https://www.cnblogs.com/scios/p/8652760.html
有关字典for循环的各种用法
原链接:https://blog.csdn.net/qq_33867131/article/details/80745926
# 1、遍历key值,value值(下面写法完全等价):
a = {'a': '1', 'b': '2', 'c': '3'}
# 方式一:
for key in a:
print(key+':'+a[key])
# 方式二:
for key in a.keys():
print(key+':'+a[key])
# 方式三:
for key,value in a.items():
print(key+':'+value)
# 方式四:
for (key,value) in a.items():
print(key+':'+value)
# 打印结果:
# a:1
# # b:2
# c:3
# 2、遍历value值:
for value in a.values():
print(value)
# 打印结果:
# 1
# 2
# 3
# 3、遍历字典项
for kv in a.items():
print(kv)
# 打印结果:
# ('a', '1')
# ('b', '2')
# ('c', '3')