视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Python爬虫初学之爬取段子
2020-11-27 14:14:20 责编:小采
文档


我们想针对网站的内容进行筛选,只获取自己感兴趣的部分。比如你想在XX网站把小黄图筛选出来,打包带走。这里只做简单的实现,以百思不得姐上的段子(纯文本)为例。我们想要实现如下功能:

  • 批量下载若干页段子到本地文件中

  • 按下任意一键,开始阅读下一条段子

  • 1. 获取网页代码

    导入urllib的相关库,Python 3中应该这样写:

    import urllib.requestimport urllib.parseimport re

    re库是正则表达式(Regular Expression),后面作匹配时会用到。

    百思不得姐的段子页面url ='http://www.budejie.com/text/1',这里末尾数字1代表此为第一页。通过以下代码就能返回网页内容。

     req = urllib.request.Request(url)# 添加headers 使之看起来像浏览器在访问req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; Win; x) AppleWebKit/537.36 ' '(KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36')
     response = urllib.request.urlopen(req)# 得到网页内容,注意必须使用decode()解码html = response.read().decode('utf-8')

    print(html)的话,就是如下所示的内容:

    这能看?段子呢?我们想要的段子呢?!

    哦对了headers这样查看。

    按F12,然后...看图吧

    2. 正则匹配提取段子

    要想筛选符合普通人阅读的内容(如果还带着html标签那还咋读是不),成功提取出段子,为此我们需要一些既定的模式去和网页全部内容进行匹配,将模式下匹配成功的对象返回。我们使用强大的正则表达式进行匹配(Regular Expression),相关语法可以看这里。

    仅仅针对本例中的网页内容,先看看我们需要的段子对应了网页中的什么内容。

    可以看到段子被<div class="j-r-list-c-desc">(我们要的内容)</div>这样的标签所包围,只需要指定相应规则提取出来即可!上图可以看出段子正文前后是有很多空格的,需要匹配进去。

    pattern = re.compile(r'<div class="j-r-list-c-desc">s+(.*)s+</div>')
    result = re.findall(pattern, html)

    通过re库的compile函数制定规则。

  • s+可以匹配一个或更多的空格

  • .匹配除开换行符 外的所有字符。

  • 现在我们得到了匹配后的结果,来看下。

    Bingo!提取出来了不是?!

    可是我们发现里面还有些讨厌的<br />。没关系,写几行代码的事。这里就不再展示去掉后的内容,自行脑补哈哈。

     for each in content:# 如果某个段子里有<br />if '<br />' in each:# 替换成换行符并
    输出new_each = re.sub(r'<br />', ' ', each)print(new_each)# 没有就照常输出else:print(each)

    这里content是我们通过re.findall()返回的列表。

    至此,我们成功得到我们想看的段子了!如果想要下载到本地呢?

    3. 下载段子到本地

    通过定义一个save()函数即可,num参数用户自定,想下载最近100页的内容都没问题!里面还有些变量没有提到,最后会给出源代码。

    # num是指定网页页数def save(num):# 写方式打开一个文本,把获取的段子列表存放进去with open('a.txt', 'w', encoding='utf-8') as f:
     text = get_content(num)# 和上面去掉<br />类似for each in text:if '<br />' in each:
     new_each = re.sub(r'<br />', '
    ', each)
     f.write(new_each)else:
     f.write(str(each) + '
    ')

    下载到本地文档后如下图所示

    4. 逐条读取段子

    段子太多,琳琅满目。可我们只希望一条条阅读。通过按下键盘任意键可以切换到下一条,直到读取到最后一条程序才结束,或者通过设置一个退出键随时退出程序,比如设定q键退出。这里把全部代码给出。

    import urllib.requestimport urllib.parseimport re
    
    pattern = re.compile(r'<div class="j-r-list-c-desc">s+(.*)s+</div>')# 返回指定网页的内容def open_url(url):
     req = urllib.request.Request(url)
     req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; Win; x) AppleWebKit/537.36 ' '(KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36')
     response = urllib.request.urlopen(req)
     html = response.read().decode('utf-8')return html# num为用户自定,返回的是所有页的段子列表def get_content(num):# 存放段子的列表text_list = []for page in range(1, int(num)):
     address = 'http://www.budejie.com/text/' + str(page)
     html = open_url(address)
     result = re.findall(pattern, html)# 每一页的result都是一个列表,将里面的内容加入到text_listfor each in result:
     text_list.append(each)return text_list# num是指定网页页数def save(num):# 写方式打开一个文本,把获取的段子列表存放进去with open('a.txt', 'w', encoding='utf-8') as f:
     text = get_content(num)# 和上面去掉<br />类似for each in text:if '<br />' in each:
     new_each = re.sub(r'<br />', '
    ', each)
     f.write(new_each)else:
     f.write(str(each) + '
    ') 
     
    if __name__ == '__main__':print('阅读过程中按q随时退出')
     number = int(input('想读几页的内容: '))
     content = get_content(number + 1)for each in content:if '<br />' in each:
     new_each = re.sub(r'<br />', '
    ', each)print(new_each)else:print(each)# 用户输入user_input = input()# 不区分大小写的q,输入则退出if user_input == 'q' or user_input == 'Q':break

    演示一下,效果是这样的。

    虽然功能很鸡肋,不过作为初学我还是很满意了,有兴趣才能深入下去嘛!爬虫可不仅仅如此而已,以后会学习更加高级的功能。


    by @sunhaiyu

    2016.8.15

    下载本文
    显示全文
    专题