BBC 爬虫 QwQ
BBC 爬虫
一只可以用来爬取 BBC 音频 和 文字材料 的网络机器人.....emmm
该爬虫只抓取网页第一页的内容, 因为懒得写页码循环了...
到了高中, 随着英语的全球化流行(逼格蛮高的), 英语考试越来越重要了, 这其中英语听力也是很重要的一部分. 因此, 多听原汁原味的音频就很重要了.emmmm
所以, 我就想写一只 BBC爬虫 ! AwA
开动啦 !
首先, 找到有BBC资料的网站. 嗯! 戳我! 我是超链接! 嗯!
打开 PyCharm.
0x01 引入模块...
# coding = utf-8
import requests # 用来做网络请求
import parsel # 用来解析网页
from urllib.request import urlretrieve # 用来下载音频
from os import mkdir #用来创建文件夹
PS: 其中的 parsel
只是用来解析网页的, 个人觉得顺手, 当然 lxml
也行...... parsel
库也可以通过pip install parsel
下载......嗯!
0x02 准备工作
# coding = utf-8
import requests
import parsel
from urllib.request import urlretrieve
from os import mkdir
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0'
} # 请求头
index_url = 'http://www.hxen.com/englishlistening/bbc/index.html' # 网页url
print(requests.get(index_url, headers=headers).text)
Run
<h3 class="fz18 YaHei fbold">
<a title="BBCÔÚÏßÊÕÌýÏÂÔØ:µÂ¹úÈ«¹úÐÔ·âËøÑÓ³¤µ½1Ôµ×" href="/englishlistening/bbc/20210107/550504.html" target="_blank">BBCÔÚÏßÊÕÌýÏÂÔØ:µÂ¹úÈ«¹úÐÔ·âËøÑÓ³¤µ½1Ôµ×</a>
</h3>
发现乱码, 肯定是编码问题, 查看网页源代码, 发现:
<meta content="text/html; charset=gb2312" http-equiv="Content-Type">
charset
为 gb2312
修改源代码:
# coding = utf-8
import requests
import parsel
from urllib.request import urlretrieve
from os import mkdir
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0'
} # 请求头
index_url = 'http://www.hxen.com/englishlistening/bbc/index.html' # 网页url
print(requests.get(index_url, headers=headers).content.decode('gb2312')) # 解码
Run
<h3 class="fz18 YaHei fbold"><a title="BBC在线收听下载:德国全国性封锁延长到1月底" href="/englishlistening/bbc/20210107/550504.html" target="_blank">BBC在线收听下载:德国全国性封锁延长到1月底</a></h3>
AwA ! 耶!
0x03 获取页面内链
# coding = utf-8
import requests
import parsel
from urllib.request import urlretrieve
from os import mkdir
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0'
}
index_url = 'http://www.hxen.com/englishlistening/bbc/index.html'
if __name__ == '__main__':
# 获取新闻日期 和 新闻对应二级深度网址
index_page = requests.get(index_url, headers=headers).content.decode('gb2312')
index_html = parsel.Selector(index_page) # 用 parsel 解析网页
# 用 css选择器 定位元素
new_dates = index_html.css('div.txtBox div.txt p.gray-8.pt5 span.gray-9.mr25::text').extract() # 新闻日期
news_titles = index_html.css('div.clearfix div h3.fz18.YaHei.fbold a::text').extract() # 新闻标题
bbc_urls = index_html.css('div.clearfix div h3.fz18.YaHei.fbold a::attr("href")').extract() # 新闻链接
bbc_names = [new_dates[i] + ' ' + news_titles[i].replace('在线收听下载:', ' ') for i in
range(len(new_dates))] # 格式化-> 新闻名字
bbc_urls = ['http://www.hxen.com' + bbc_url for bbc_url in bbc_urls] # 新闻直链
print(bbc_names)
print('=' * 100)
print(bbc_urls)
Run
['2021-02-03 BBC 拜登发声明“威胁”对缅甸实施新制裁', '2021-02-02 BBC 缅甸发生政变 领导人昂山素季被“扣押”', '2021-02-02 BBC 世卫专家组走访武汉市医院', '2021-01-31 BBC 拜登签署行政令 重启奥巴马医改', '2021-01-29 BBC 美国总统拜登签署行政令应对气候问题', '2021-01-28 BBC 全球累计新冠肺炎确诊病例超过1亿例', '2021-01-27 BBC 拜登提高疫苗接种目标,上任百日完成1.5亿剂', '2021-01-27 BBC 墨西哥总统称自己感染新冠病毒', '2021-01-26 BBC 香港首次实施“封区抗疫”', '2021-01-24 BBC 拜登签署行政命令强制戴口罩', '2021-01-22 BBC 拜登正式入主白宫 上台首日狂签行政令', '2021-01-21 BBC 特朗普发表告别演讲:祝新政府成功', '2021-01-20 BBC 巴西开始接种中国新冠疫苗', '2021-01-19 BBC 巴西紧急批准使用中国科兴和牛津疫苗', '2021-01-18 BBC 危地马拉难民涌向美国', '2021-01-17 BBC 美众议院投票弹劾总统特朗普', '2021-01-15 BBC 美国FBI对袭击国会大厦的人员进行刑事调查', '2021-01-14 BBC 国会骚乱后特朗普首次露面 不承认为骚乱负责', '2021-01-14 BBC FBI警告称全美或爆发“武装抗议”', '2021-01-12 BBC 美国副总统彭斯将出席拜登就职典礼', '2021-01-11 BBC 美众议院民主党人已撰写弹劾特朗普草案', '2021-01-10 BBC 美国国会确认乔・拜登当选美国总统', '2021-01-08 BBC 美国佐治亚州决选结果进入最后倒计', '2021-01-07 BBC 德国全国性封锁延长到1月底', '2021-01-07 BBC 英国新冠疫情严重 再次实施封锁措施']
====================================================================================================
['http://www.hxen.com/englishlistening/bbc/20210203/551898.html', 'http://www.hxen.com/englishlistening/bbc/20210202/551832.html', 'http://www.hxen.com/englishlistening/bbc/20210202/551831.html', 'http://www.hxen.com/englishlistening/bbc/20210131/551717.html', 'http://www.hxen.com/englishlistening/bbc/20210129/551649.html', 'http://www.hxen.com/englishlistening/bbc/20210128/551576.html', 'http://www.hxen.com/englishlistening/bbc/20210127/551458.html', 'http://www.hxen.com/englishlistening/bbc/20210127/551453.html', 'http://www.hxen.com/englishlistening/bbc/20210126/551335.html', 'http://www.hxen.com/englishlistening/bbc/20210124/551190.html', 'http://www.hxen.com/englishlistening/bbc/20210122/551118.html', 'http://www.hxen.com/englishlistening/bbc/20210121/551078.html', 'http://www.hxen.com/englishlistening/bbc/20210120/551027.html', 'http://www.hxen.com/englishlistening/bbc/20210119/550955.html', 'http://www.hxen.com/englishlistening/bbc/20210118/550914.html', 'http://www.hxen.com/englishlistening/bbc/20210117/550889.html', 'http://www.hxen.com/englishlistening/bbc/20210115/550823.html', 'http://www.hxen.com/englishlistening/bbc/20210114/550788.html', 'http://www.hxen.com/englishlistening/bbc/20210114/550787.html', 'http://www.hxen.com/englishlistening/bbc/20210112/550703.html', 'http://www.hxen.com/englishlistening/bbc/20210111/550662.html', 'http://www.hxen.com/englishlistening/bbc/20210110/550642.html', 'http://www.hxen.com/englishlistening/bbc/20210108/550555.html', 'http://www.hxen.com/englishlistening/bbc/20210107/550504.html', 'http://www.hxen.com/englishlistening/bbc/20210107/550503.html']
Process finished with exit code 0
成功!
为了之后筛选方便, 我们将 新闻日期 和 新闻对应二级深度网址 对应为字典
# coding = utf-8
import requests
import parsel
from urllib.request import urlretrieve
from os import mkdir
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0'
}
index_url = 'http://www.hxen.com/englishlistening/bbc/index.html'
if __name__ == '__main__':
# 获取新闻日期 和 新闻对应二级深度网址
index_page = requests.get(index_url, headers=headers).content.decode('gb2312')
index_html = parsel.Selector(index_page)
new_dates = index_html.css('div.txtBox div.txt p.gray-8.pt5 span.gray-9.mr25::text').extract() # 新闻日期
news_titles = index_html.css('div.clearfix div h3.fz18.YaHei.fbold a::text').extract() # 新闻标题
bbc_urls = index_html.css('div.clearfix div h3.fz18.YaHei.fbold a::attr("href")').extract() # 新闻链接
bbc_names = [new_dates[i] + ' ' + news_titles[i].replace('在线收听下载:', ' ') for i in
range(len(new_dates))] # 格式化-> 新闻名字
bbc_urls = ['http://www.hxen.com' + bbc_url for bbc_url in bbc_urls] # 新闻直链
# 将 新闻日期 和 新闻对应二级深度网址 对应为字典
name_url = zip(bbc_names, bbc_urls)
audio_dict = dict((name, value) for name, value in name_url)
0x04 然后, 我们来写获取每个二级深度网址的代码
def get_audio_lines(url, dir_name):
"""获取音频和原文"""
page = requests.get(url, headers=headers).content.decode('gb2312') #网页请求
html = parsel.Selector(page) # 解析网页
mp3_url = html.css('div.mp3player a::attr("href")').extract_first() # 获取音频直链
lines = html.css('div#arctext p::text').extract() # 获取原文内容
try:
mkdir(dir_name)
except OSError: # 可能包含问号, 导致无法成功创建文件夹
dir_name = dir_name.replace('?', ' ')
mkdir(dir_name)
urlretrieve(mp3_url, './{}/BBC.mp3'.format(dir_name)) # 获取音频
with open('./{}/BBC(原文).txt'.format(dir_name), mode='w+', encoding='utf-8') as lines_file:
lines_file.writelines([line+'\n' for line in lines]) # 保存原文
print('已下载 {} 的 音频 和 原文\n'.format(dir_name)) # 输出结果
至此, 爬虫大部分都完成了
还剩下记录已经下载过的音频, 和遍历直链进行下载了
0x05 收尾工作
try:
with open(r'./dates.txt', mode='r', encoding='utf-8') as f:
old_news = f.readlines() # 读取已下载新闻
except FileNotFoundError:
old_news = []
# 遍历下载
count = 1
with open(r'./dates.txt', mode='a+', encoding='utf-8') as f:
for bbc_name in bbc_names:
if bbc_name + '\n' in old_news:
del audio_dict[bbc_name]
else:
print('新增条目<{}> : {}'.format(count, bbc_name))
get_audio_lines(audio_dict[bbc_name], bbc_name)
f.writelines(bbc_name + '\n') # 记录已下载新闻
count += 1
# 输出
if len(audio_dict) == 0:
print('BBC未更新哦! 么么哒!')
else:
print('下载完成啦! 么么哒! ')
芜湖!!!!!!!!完成了!!!!!!!!!!!!!
0x06 完整代码
"""
该爬虫只抓取第一页的内容, 因为懒得写页码循环了...
"""
# coding = utf-8
import requests
import parsel
from urllib.request import urlretrieve
from os import mkdir
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0'
}
index_url = 'http://www.hxen.com/englishlistening/bbc/index.html'
def get_audio_lines(url, dir_name):
page = requests.get(url, headers=headers).content.decode('gb2312')
html = parsel.Selector(page)
mp3_url = html.css('div.mp3player a::attr("href")').extract_first()
lines = html.css('div#arctext p::text').extract()
try:
mkdir(dir_name)
except OSError:
dir_name = dir_name.replace('?', ' ')
mkdir(dir_name)
urlretrieve(mp3_url, './{}/BBC.mp3'.format(dir_name))
with open('./{}/BBC(原文).txt'.format(dir_name), mode='w+', encoding='utf-8') as lines_file:
lines_file.writelines([line+'\n' for line in lines])
print('已下载 {} 的 音频 和 原文\n'.format(dir_name))
if __name__ == '__main__':
# 获取新闻日期 和 新闻对应二级深度网址
index_page = requests.get(index_url, headers=headers).content.decode('gb2312')
index_html = parsel.Selector(index_page)
new_dates = index_html.css('div.txtBox div.txt p.gray-8.pt5 span.gray-9.mr25::text').extract() # 新闻日期
news_titles = index_html.css('div.clearfix div h3.fz18.YaHei.fbold a::text').extract() # 新闻标题
bbc_urls = index_html.css('div.clearfix div h3.fz18.YaHei.fbold a::attr("href")').extract() # 新闻链接
bbc_names = [new_dates[i] + ' ' + news_titles[i].replace('在线收听下载:', ' ') for i in
range(len(new_dates))] # 格式化-> 新闻名字
bbc_urls = ['http://www.hxen.com' + bbc_url for bbc_url in bbc_urls] # 新闻直链
# 将 新闻日期 和 新闻对应二级深度网址 对应为字典
name_url = zip(bbc_names, bbc_urls)
audio_dict = dict((name, value) for name, value in name_url)
try:
with open(r'./dates.txt', mode='r', encoding='utf-8') as f:
old_news = f.readlines()
except FileNotFoundError:
old_news = []
count = 1
with open(r'./dates.txt', mode='a+', encoding='utf-8') as f:
for bbc_name in bbc_names:
if bbc_name + '\n' in old_news:
del audio_dict[bbc_name]
else:
print('新增条目<{}> : {}'.format(count, bbc_name))
get_audio_lines(audio_dict[bbc_name], bbc_name)
f.writelines(bbc_name + '\n')
count += 1
if len(audio_dict) == 0:
print('BBC未更新哦! 么么哒!')
else:
print('下载完成啦! 么么哒! ')