美文网首页
爬取一BBS论坛所有帖子名

爬取一BBS论坛所有帖子名

作者: 大邓和他的python | 来源:发表于2016-08-29 17:19 被阅读546次
    人生苦短,何不python

    爬取中国政法大学的 法大BBS,之前的IP被封掉了。今天我改了下代码,加入了休息时间,降低访问的频率。

    首先要爬该BBS里所有的标题,那么首先应该知道是哪个版块的,版块的链接是什么,这些链接的特点有什么规律吗,还有保存起来。

    打开浏览器,按住F12键,查看DOM节点,发现版块名,链接都是处于“dt”标签中,而且查看页面源码,按住Ctrl+F查找''dt'',发现刚好35个,正好与版块的个数相等。

    上面解决了版块链接、版块名的问题,查看各个板块的页码数也与上面方法类似。只要找到唯一的能确定的标签就能抓取。

    # -*- coding=utf-8 -*-
    
    from bs4 import BeautifulSoup
    import urllib.request
    import time
    
    
    #获取板块的链接
    def get_Bankuan_link(url):
        link_list = []  #用来收集板块的链接
        html = urllib.request.urlopen(url)
        bsObj = BeautifulSoup(html, "lxml")
        #bsObj.find_all('dt')返回的是列表,所以要遍历
        for node in bsObj.find_all('dt'):
        # 遍历每个<dt>节点内的节点,
        #如<a href="forum.php?mod=forumdisplay&fid=67">校园生活</a>
        #来获取链接和板块名字
            try:
                node_link = node.contents[0]['href']
                node_html = urllib.request.urlopen(url + node_link)
                node_bsObj = BeautifulSoup(node_html,"lxml")  #进入板块内
                judge = node_bsObj.find('input', {'name': 'custompage'})#找到页码所对应的代码
                if judge is not None: #判断该板块是否有页码
                    link_list.append(node_link)
            except:
                continue
            time.sleep(1)
    
        #link_list.append(node_link)
        return link_list  #返回列表
    
     
    
    #获取板块名
    def get_Bankuan_name(url):
        name_list = []  #用来收集板块名
        html = urllib.request.urlopen(url)
        bsObj = BeautifulSoup(html, "lxml")
        #bsObj.find_all('dt')返回的是列表,所以要遍历。另外要清理不合规矩的板块
        for node in bsObj.find_all('dt'):
            try:
                node_link = node.contents[0]['href']
                node_html = urllib.request.urlopen(url + node_link)
                node_bsObj = BeautifulSoup(node_html, "lxml")
                judge = node_bsObj.find('input', {'name': 'custompage'})
                if judge is not None:
                    name_list.append(node.contents[0].string)
            except:
                continue
            time.sleep(1)
        return name_list
    
    
    
    #获取板块最大页数
    def get_page_max_list(url,error_count = 1):  #error_count=1方面函数内全局的对错误的计数不受for限制
        page_max_list = []
        Bankuan_link_list = get_Bankuan_link(url)  #获取板块的链接,返回的是列表类型
        Bankuan_name_list = get_Bankuan_name(url) #获取板块的名,列表
        for x in Bankuan_link_list:  
            html = urllib.request.urlopen(url + x)
            bsObj = BeautifulSoup(html, "lxml")
            error = Bankuan_link_list.index(x)   #error变量是为了后面遇到问题时候能标记到底是哪个板块的问题
            error_Bankuan_name = Bankuan_name_list[error]
            try:
                num = bsObj.find('input', {'name': 'custompage'}).next_sibling.string[3:-2]  #[3:-2]收集字符串从左起第四个  与   从右起倒数第二个  之间的字符串
                page_max_list.append(num)
            except:
                print("Error%d: "%error_count,"%s 版块的get_page_max_list无法解决该板块,"需要自己动手查找该页面页数"%error_Bankuan_name,'\n',  "该版块的网址是: http://bbs.csu.edu.cn/bbs/%s "%x, '\n'
                  "在版块名、版块链接列表中的第%d位置"%error)
                print("="*100)
                error_count = error_count + 1   
            time.sleep(1)
        return page_max_list
    
    
    
    #base_url:BBS的链接
    #bankuan_url:BBS内某一板块的url
    def get_BBS_all_article_title(file_name, pages_count, bankuan_url, base_url ='http://bbs.csu.edu.cn/bbs/', title_count = 1):
        file_name = file_name+'.txt'
        f = open(r'E:/Python/Spider_Net/未爬取的BBS/%s'%file_name, 'a')
        html = urllib.request.urlopen(base_url+bankuan_url)
        print('正在写入%s文件'%file_name)
        for x in range(int(pages_count)):
            page_num = x + 1
            URL = base_url + bankuan_url + '&page=%d'%page_num
            html = urllib.request.urlopen(URL)
            #print('='*20,'正在写入%s文件'%file_name,'已经写了%d条帖子标题'%numlist_of_title)
            try:
                html = html.read().decode('gbk')
            except:
                continue
            bsObj = BeautifulSoup(html, "lxml")
            JieDian = bsObj.find_all("a", {"class": "s xst"})
            for y in JieDian:
                print(' ' * 15, '正在写入 %s文件' % file_name, '  已经写了%d条帖子标题' % title_count, y.string)
                try:
                    f.write(y.string + '\n')
                    title_count = title_count + 1
                except:
                    continue
            time.sleep(1)
    
    
    ===========================================================
    
    #初始化bbs的链接
    base_url = 'http://bbs.cupl.edu.cn/'
    
    File_name = get_Bankuan_name(base_url)
    Pages_count = get_page_max_list(base_url)
    Bankuan_link = get_Bankuan_link(base_url)
    print(File_name)
    print(Pages_count)
    print(Bankuan_link)
    
    
    for i in range(len(File_name)):
        file_name = File_name[i]
        pages_count = Pages_count[i]
        bankuan_link = Bankuan_link[i]
        get_BBS_all_article_title(file_name, pages_count, bankuan_link,base_url)
    

    完美!

    欢迎关注
    微信公众号:大邓带你玩转python

    大邓带你玩转python
    每周有直播哦,扫码即可加入

    相关文章

      网友评论

          本文标题:爬取一BBS论坛所有帖子名

          本文链接:https://www.haomeiwen.com/subject/pioxettx.html