爬取学校官网新闻-bs与xpath的恩怨情仇

为了更好地学习《自然语言处理》这一门课,我们的老师叫我们组团去刷学校官网,我刚开始还以为很简单,事实证明,我错了,固执的凭借xpath去解析内容非常的难,还有我最后用bs4轻松解析,这个项目让我看清了xpath适合提取单个标签内的内容,而bs4明显适合去提取大段的内容,然后再通过join,strip,replace,split等内容就可以去掉转义字符,空格和转换为列表。

另外,老师也要求我们使用正则表达式,我用正则表达式去提取特定格式的时间还有在提取出来的文本内容中提取出最后一个括号内的内容,也就是发布人信息,虽然会有点偏颇,但是还是可以接受的;在之前使用xpath去提取内容的时候,我还发现table下的tbody不可以写入xpath,如果写进来会导致错误,这是因为tbody很可能是谷歌或者火狐浏览器自动加上去的,大坑!

下面附上源代码:

import requests
import re
from lxml import etree
from bs4 import BeautifulSoup
import time
import sys
#步骤一:提取网页内容
start_time=time.time()
# print(start_time)
url='http://web.fosu.edu.cn/school-news'
#请求方式为get
rsp=requests.get(url)
soup = BeautifulSoup(rsp.text, "lxml")

#步骤二:提取想要的网页url
def geturl(rsp):
    html=etree.HTML(rsp.text)
    soup = BeautifulSoup(rsp.text, "lxml")
    # print(html)
    #获取想要的文章的url
    url=html.xpath('//li[@class="category-content"]/a/@href')
    # print(url)
    end_time = time.time()
    print(int(end_time-start_time),'s')
    for i in url:
        go(i)

    # 获取下一页的url,观察页面可知a标签倒数第二个属性href就是下一页的url
    next_url = html.xpath('//div[@class="pagination"]/center/a[last()-1]/@href')[0]
    print(next_url)
    #设定停止程序的时刻
    if next_url=='http://web.fosu.edu.cn/school-news/page/342':
        if html.xpath('//div[@class="pagination"]/center/a[@class="current"]/text()')[0]=='343':
            sys.exit()#退出程序
    next(next_url)

#步骤三:通过url访问文章,获取标题,时间,发布人,内容
def go(url):
    rsp=requests.get(url)
    html=etree.HTML(rsp.text)
    soup = BeautifulSoup(rsp.text, "lxml")
    name=html.xpath('//div[@class="single-newstitle"]/text()')
    # print(name)
    time=re.compile('2ddd-dd-dd').findall(str(html.xpath('//div[@class="single-newstime"]/text()')[0]))
    # print(type(time))
    for i in soup.find_all('div',class_='single-content'):
        content=i.get_text()
    #在使用xpath爬取table的时候,不要写tbody,写入tbody会查找不到,因为这是Chrome和火狐浏览器自动加的标签,大坑!
    content = ''.join(content).strip()#去掉所有的转移字符!
    content = content.replace('
', '').replace('	', '').replace('xa0', '').replace('
','')#去掉字符串里面的
txa转义字符

    try:
        people = re.findall('((.*?))', content)[-1]
        #因为选取的是最后一个小括号内的内容,所以发布人可能出错,并且有些新闻没有发布人
        people = people.split('*')
    except:
        people=['无']
        #可能出现爬取文本内容没有括号的情况,也允许这种误差,因此找不到的时候就设为[]
    content = content.split('*')#*是随便设置的一个字符串里面不可能存在的字符,为了把字符串转换为列表

    # print(name,time,people,content)
    #保存在csv文件中
    for i,j,k,l in zip(name,time,people,content):
        params=str((i,j,k,l))
        # print(params)
        with open('fosu.csv','a',encoding='utf-8')as f:
            f.write(params+'
')

#步骤四:访问下一页
def next(url):
    rsp=requests.get(url)
    geturl(rsp)

if __name__=="__main__":
    geturl(rsp)

  

原文地址:https://www.cnblogs.com/fodalaoyao/p/10466492.html