爬取中国政法大学的 法大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
每周有直播哦,扫码即可加入
网友评论