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">

charsetgb2312

修改源代码:

# 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('下载完成啦! 么么哒! ')

posted @ 2021-02-04 13:33  不爱喝橙子汁的橙子  阅读(635)  评论(0编辑  收藏  举报