Python爬虫爬取某会计师协会网站的指定文章(文末送书)

news2025/3/1 11:56:38

🤵‍♂️ 个人主页:@艾派森的个人主页

✍🏻作者简介:Python学习者
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+


目录

一、Python编写爬虫的优势

二、Python爬虫爬取会计师协会网站的指定文章

三、文末推荐与福利


一、Python编写爬虫的优势

  1. 易学易用:Python的语法简单明了,易于理解和学习,使得编写爬虫变得简单容易。
  2. 强大的第三方库:Python有很多强大的第三方库,如requests、BeautifulSoup、Scrapy、Selenium等,可以帮助我们轻松实现网页的请求、解析和数据的提取等功能。
  3. 跨平台性:Python可运行于Windows、Linux、macOS等多个操作系统上,使得在多个平台上编写和运行爬虫变得简单容易。
  4. 处理文本信息方便:Python对文本处理非常方便,支持多种文本编码,可以轻松实现数据的清洗和去重。
  5. 丰富的数据处理和分析工具:Python拥有众多的数据处理和分析工具,如NumPy、Pandas、Matplotlib等,可以对爬取的数据进行深入的分析和处理。
  6. 自动化:Python可以轻松实现自动化,可以自动执行爬取任务,定时发送邮件等,大大提高工作效率。
  7. 反爬虫机制容易应对:Python可以通过设置User-Agent、Cookie等方式来模拟浏览器行为,避免被目标网站的反爬虫机制识别和封锁。

二、Python爬虫爬取会计师协会网站的指定文章

        由于业务原因,需要经常关注`“北京注册会计师协会”`网站`“最新公告”`栏目里的`“北京注册会计师协会专业技术委员会专家提示”`相关文章。不想每次进网站一个一个地点击,然后复制到word文件。如果能一次批量爬取,并存到word文件就好啦。

        此处用到两个库,`“requests”`和`“beautifulsoup”`。`“requests”`用于发送HTTP请求,并获取网页的内容。`“beautifulsoup”`用于解析获取到的网页内容,非常简单又方便地为用户提供需要抓取的数据,比如文字内容,图片链接等。若未安装,则运行cmd,输入`pip install requests`及`pip install beautifulsoup4`。

        库准备好后,就可以开始爬虫之旅了。先随便选择一篇文章,点击进去,看看网页的情况。单个文章的网页的`Request Method`(请求方法)一般都是`get`。如果不确定,可以点击"Network",然后刷新页面,在左侧"Name"栏选第一个文件,然后再选"Headers"查看"Request Method"。由于请求方法是`get`,所以我们用`requests`获取链接信息的时候就要用`get`。将获取到的链接信息传递给`wb_data`变量,然后调用`BeautifulSoup`进行解析。此处,我们传入`BeautifulSoup`中的参数是`wb_data.content`,表示是二进制数据。还有一种是`wb_data.text`,表示是Unicode型的数据。由于使用`.text`,`soup`变量里的中文显示为乱码,所以此处使用`.content`。最后显示`soup`,就能看到这个网页里的信息。我们需要的文章标题和内容都在里面。

import requests
from bs4 import BeautifulSoup

url = 'http://www.bicpa.org.cn/dtzj/zxgg/B15903912099325.html'
wb_data = requests.get(url)
soup = BeautifulSoup(wb_data.content)
soup

        由于只想要标题和正文,所以直接在标题上点右键,选择“检查”(此处用谷歌Chrome浏览器)。浏览器右边出现如下窗口。可见标题对应的`class`为`headword`。因此,可以在soup中使用`select`方法,传入`.headword`获取这个`class`里的信息("."就表示按"class"选择)。我们可以看到标题连带一些语句信息就提取出来并存入了一个列表,这个列表中只有1个元素。

soup.select('.headword')

 然后使用`.text`方法将这个列表中的文本提取出来,并用`strip()`去掉首尾的空格,存到`title`变量。显示一下,就得到完整的标题。

#获取文章标题
title = soup.select('.headword')[0].text.strip()
title

        类似的方法,可以获取到正文文本。通过“检查”正文文本,发现正文位于`class = MsoNormal`下面。因此使用`soup.select(".MsoNormal")`按`class`选取,其中的"."就表示`class`。正文内容存到列表`content`,要提取其文本内容,需要遍历这个列表,然后分别按文本提取。还有一部分文章的正文位于`id = "art_content"`下面,则需要使用`soup.select("#art_content")`来获取,“#”就表示`id`。这样,我们就成功地提取出了一篇文章的内容。 

#获取正文文本
content = soup.select(".MsoNormal")
for i in content:
    print(i.text)

        是不是有点嘚瑟啊?慢着,别骄傲,万里长征才走完小小的一步。这个爬虫的难度在于获取所有4000多篇文章的链接。观察每篇文章的链接,没发现什么规律。而且通过点击“下一页”,网页的网址没有变化,始终是“http://www.bicpa.org.cn/dtzj/zxgg/index.html” 。这说明翻页时,网页是异步加载的,直接使用`get`方法去获取,是不能获取到那些文章链接的。

        我们再从浏览器进到以上链接,点右键,选择“检查”。右边窗口出现如下界面,按顺序选择"Network","XHR",`Name`里面最下面的"getAtricles.action","Headers"。可以看到请求的URL,以及请求方法(是`POST`)。为什么要针对性地选"XHR"呢,因为它就是实现异步加载的,其全称是`XMLHttpRequest`。如果选"All"会显示所有,不利于快速锁定目标。还有问题,为什么是`Name`里面最下面那个?因为通过观察,发现网页在刷新的时候,文章列表最后出现,而且`Name`里面最后一个的名字翻译成中文,正好是“获取文章”。

         找到了获取文章列表的URL和请求方法,还需要知道其数据提交格式。将上图右边的滚动条拖到最下面,可以看到`Form Data`,这个就是数据提交格式了。注意`start`和`limit`的值,这个表示文章的开始数和最多文章数。第一次的`getAtricles.action`,`start`是1,`limit`是15,表示显示1~15篇文章,这个正是第一页显示的文章总数。然后我们手动点一下网页中的“下一页”,马上出现第二次`getAtricles.action`,这次`start`变成了15了,`limit`不变,因为文章显示页面只够显示15篇文章。这样我们就知道怎么通过Python去模拟浏览器请求数据了。

        说干就干,先导入`requests`库,定义一个`header`,将下图`Headers`中的`User-Agent`连同后面一串字符复制过来。为什么要搞这个呢?是为了将程序伪装成一个浏览器,避免对方服务器发现是爬虫程序而拒绝访问。如果网站没有这些反爬虫设置,也可以不搞这个伪装。小心驶得万年船,搞起放心点。 

        然后将`Form Data`里的所有内容也复制过来,做成字典的格式,存入`form_data`字典,注意`start`和`limit`的值是整数,不能是字符串。这里直接将`limit`改成5000,一次性获取所有文章的链接信息,而不是像网页上点击那样,以15个为一段去获取。为什么是5000呢,因为文章总数是4946个,所以5000够用了。再复制`Resquest URL`,存入`url`变量。然后调用`requests.post`,传入`url`,`data`和`headers`参数,开始获取,最后显示其文本。

import requests

header = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36'}

form_data = {'_q': 'Article.list',
'siteId': '7e0b3b27-2622-4aa7-b6f8-abfe5c5df922',
'catalogId': '34f92da3-d6d0-4e96-899f-d7f581c18162',
'pub': 'true',
'limit': 5000,
'start': 1}

#这是异步加载,请求方法是POST
url = "http://www.bicpa.org.cn/dtzj/zxgg/getArticles.action"
res = requests.post(url, data = form_data, headers = header)

res.text

        以上运行内容是一个超级大的字符串,里面存着4946篇文章的基本信息。我们需要使用`json`将其转换成Python能够处理的数据,以便从中提取需要的信息。在此之前,需要将字符串首尾无关数据去掉(下图红色部分),才能满足`json`能够识别的格式。

article_data0 =res.text.split("{success:true,datas:")[1] #去掉字符串前面的无用信息“{success:true,datas:”
article_data = article_data0.split(",total:")[0] #去掉字符串后面的无用信息“,total:4946}”
article_data

         我们观察`article_data`,它其实是一个超大字符串,如果将首尾的`'`去掉,它就是一个Python列表,列表中有很多字典,每个字典存储的就是每篇文章的基本信息。`json`的作用就是将这个超大字符串转换成Python能够识别的列表,这样我们才能从中提取需要的数据。将字符串`article_data`传入`json.loads()`即可完成转换。`loads`意思是`load string`,即加载字符串。转化后的数据存入`obj`,查看其类型,显示为`list`,即列表。然后我们看一下`obj`有多少数据,正好4946条,对应文章总数。用`obj[0]`显示第一条数据,真个眉清目秀啊。

import json
obj = json.loads(article_data)
type(obj)

len(obj)

 

obj[0]

        然后,我们就开始逐条将需要的信息抽取出来。我们需要的数据有`title`、`publishDate`、`primaryKey`和`url`,分别表示文章标题、发布时间、文章链接编号及文章链接。通过观察单篇文章的链接,都是“http://www.bicpa.org.cn” 加`url`,再加上`primaryKey`和“.html”。

        由于我只对“专家提示”相关的文章感兴趣,所以用了一个`if`语句来限制,只有标题含有“委员会专家提示”字符的才获取其信息。获取的信息存入字典`article`,再加入总文章列表`articles`。最后查看其前5项。

#获取标题含有“委员会专家提示”的文章的标题,发布时间和链接
path = r"http://www.bicpa.org.cn"
articles = []
for info in obj:
    if "委员会专家提示" in info['title']:
        article = {
            "标题": info['title'].strip(), #strip()去除首尾空格
            "发布时间": info['publishDate'],
            "链接": path + info['url'] + info['primaryKey']+".html"             
        }
        articles.append(article)

articles[:5]

len(articles)

        需要的信息获取完成后,就可以逐个爬取文章并写入word文档了。如下定义了一个函数`Get_article_to_word`,其中有两个参数,一个是`url`,即文章的链接;另一个是`date`,即文章的发布时间。

        然后建了一个浏览器列表`user_agent_list`,里面放入了7个浏览器信息,以便在爬取文章的时候从里面随机选取,避免单个浏览器请求太快而被服务器拒绝访问。

        在获取正文的时候,有些正文布局为“class = "MsoNormal"”;有些则是“id = "art_content"”;还有些是两者都有,“class”负责正文中表格的部分,“id”负责正文部分。因此建了两个变量,`content1`和`content2`,无论有无,将两个信息都获取。在写入到word文件时,先写`content2`的,再写`content1`的,这样能保证正文在前,表格在后。

#获取想要的文章并批量写入word文件
import requests
from bs4 import BeautifulSoup
import docx
from docx.shared import Pt #用于设定字体大小(磅值)
from docx.oxml.ns import qn #用于应用中文字体
import random
import time

def Get_article_to_word(url,date):
    user_agent_list = ["Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
                    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
                    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
                    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36",
                    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36",
                    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
                    "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15"
                    ]
    header = {'User-Agent': user_agent_list}
    header['User-Agent'] = random.choice(user_agent_list) #每篇文章随机选择浏览器,避免单个浏览器请求太快被服务器切断连接
    wb_data = requests.get(url,headers = header)
    soup = BeautifulSoup(wb_data.content)
    title = soup.select('.headword')[0].text.strip()#获得标题
    content1 = soup.select(".MsoNormal") #针对正文布局为 class = "MsoNormal"
    content2 = soup.select("#art_content") #针对正文布局为 id = "art_content"
    
    doc = docx.Document() #新建空白word文档
    #设定全局字体
    doc.styles['Normal'].font.name=u'宋体'
    doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
   
    #写入标题行,并设置字体格式
    p = doc.add_paragraph()
    r = p.add_run(title)
    r.bold = True
    r.font.size = Pt(18)
    
    doc.add_paragraph(date) #写入日期
    doc.add_paragraph(url) #写入文章链接
    
    #写入正文
    for i in content2:
        doc.add_paragraph(i.text)
    for i in content1:
        doc.add_paragraph(i.text)
    doc.save(f"文章\\{title}.docx")

#遍历所有文章的链接,调用以上函数执行
for art in articles:
    Get_article_to_word(art["链接"],art["发布时间"])
    print("{} 下载完成。".format(art['标题']))
    if articles.index(art) % 30 == 29: #每获取30篇文章,暂停5秒,避免频繁请求被服务器切断连接
        time.sleep(5)
          
print(f"共下载 {len(articles)} 篇文章。")

爬取的文章如下。好了,睡午觉去了。

三、文末推荐与福利

《硅基物语 AI写作高手》免费包邮送出3本!

内容简介:   

        本书从写作与ChatGPT的基础知识讲起,结合创作者的实际写作经历与写作教学经历,重点介了用ChatGPT写作的基础技巧、进阶写作的方法、不同文体的写作方法、写作变现的秘诀,让读者系统地理解写作技巧与变现思路。本书包括如下内容:用ChatGPT重建写作思维、快速摘定选题、快速写出标题、高效收集索材、生成文章结构、写出优质文章、进行日常写作训练,以及用ChatGPT提升写作变现能力。本书适合零基础想学习写作、想利用ChatGPT提高写作能力的读者阅读。
        本书适合零基础想学习写作、想利用ChatGPT提高写作能力的读者阅读。

编辑推荐:

覆盖常用写作场景:写小说、写故事、写文案、写策划、写新媒体文章、写广告卖点……
提高写作效率:输入有效提问关键词,一键生成所需内容,稍加修改便成一篇完整文章,将写作效率成百倍提升。
扩大素材积累:作为天生的超大型素材库,只有你想不到的素材,没有AI无法提供的素材,极大充实素材库,让写作不再无内容可写。
快速进行文本精修:文稿写完只完成了第一步,修改校对仍是重中之重。AI自带语句精修功能,可对文稿的内容、结构、标点符号等进行全方位的修订,让稿件修改更轻松、更精细。

  • 抽奖方式:评论区随机抽取3位小伙伴免费送出!
  • 参与方式:关注博主、点赞、收藏、评论区评论“人生苦短,拒绝内卷!”(切记要点赞+收藏,否则抽奖无效,每个人最多评论三次!
  • 活动截止时间:2023-10-16 20:00:00
  • 京东购买链接:https://item.jd.com/13856373.html

  • 当当网购买链接:http://product.dangdang.com/29626355.html

 名单公布时间:2023-10-16 21:00:00  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1087013.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

苹果ios用户下载ipa文件内测签名的后的app应用下载安装到手机图标消失了-解决方案

下载好的应用竟然找不到了?这么神奇?我尝试了解了一下复原了同学给我的内容果然出现了我尝试科技了一下,总结了以下的可能性!同学如果这个回答解决了你的困扰,同学给个赞,如果你有更好的排查方案评论区分享…

解锁知识管理3.0,生成式人工智能洞察新时代

原创 | 文 BFT机器人 鉴于我们不断使用最新、最好的解决方案,软件、技术和计算创新的巨大飞跃可能具有挑战性。人们很容易忘记技术过去的困境。但对于依赖及时信息和数据的行业(例如企业知识管理)来说,最新的管理技术能带来了巨大…

机器人革命:脑洞大开的前沿机器人技术!

原创 | 文 BFT机器人 01 由生物启发的多模式移动形态机器人 在一个不断运动的世界中,一种新开发的名为M4(多模式移动形态机器人)的机器人展示了在包括滚动、飞行和行走在内的八种不同运动模式之间切换的能力。这款机器人由加州理工学院自主…

Spring Boot 中的 TransactionTemplate 是什么,如何使用

Spring Boot中的TransactionTemplate:简化事务管理 事务管理是任何应用程序中至关重要的部分,特别是在处理数据库操作时。Spring Boot提供了多种方式来管理事务,其中之一是使用TransactionTemplate。本文将深入探讨TransactionTemplate是什么…

MFC为“对话框中的控件添加变量”,QT中使用“ui.对象名称”来调用控件

MFC中使用 向导 可以为“对话框中的控件添加变量”; 但是在QT中,一般都是使用“ui.对象名称”来调用控件! 1、MFC中为“对话框中的控件添加变量”; 1.1 因为编辑框中的数据可能会经常变化,所以需要它们每个控件关联个…

Java多线程——线程状态以及线程礼让,线程休眠的区别(基于狂神说的学习笔记)

线程状态 线程的生命周期: 线程方法: 方法说明setPriority(int newPriority)更改线程的优先级static void sleep (long millis)在指定的毫秒数内让当前正在执行的线程体休眠void join ()等待该线程终止static void yield()暂停当前正在执行的线程对象&…

Vue-2.2组件通信

组件通信 指组件与组件之间的数据传递。 组件的数据是独立的,无法直接访问其他组件的数据。 想用其他组件的数据->组件通信 组件关系分类 1.父子关系 通信:props和$emit 1)父组件通过props将数据传递给子组件 prop定义:…

Docker 的数据管理和Dockerfile镜像的创建

目录 Docker 的数据管理 管理 Docker 容器中数据的方式 端口映射 容器互联(使用centos镜像) Docker 镜像的创建 Dockerfile 操作常用的指令 编写 Dockerfile 时格式 Dockerfile 案例 Docker 的数据管理 管理 Docker 容器中数据的方式 管理 Doc…

使用【Blob、Base64】两种方式显示【文本、图片、视频】 使用 video 组件播放视频

Blob 显示 Blob 对象的类型是由 MIME 类型(Multipurpose Internet Mail Extensions)来确定的。MIME 类型是一种标准,用于表示文档、图像、音频、视频等多媒体文件的类型。以下是一些常见的 Blob 对象类型: text/plain&#xff1…

华为数通方向HCIP-DataCom H12-831题库(单选题:241-260)

第241题 某园区部署了IPV6进行业务测试,该网络中有4台路由器(R1R2、R3和R),运行OSPFV3实现Pv6网络的互联互通。有一台新的路由器R5需要接入网络进行测试,某工程师通过在R4的OSPFV3进程中引入直连路由,实现园区网内的设备能够访问R5的GEO/0/1口地址。关千该场景的描述,错误…

RabbitMq启用TLS

Windows环境 查看配置文件的位置 选择使用的节点 查看当前节点配置文件的配置 配置TLS 将证书放到同配置相同目录中 编辑配置文件添加TLS相关配置 [{ssl, [{versions, [tlsv1.2]}]},{rabbit, [{ssl_listeners, [5671]},{ssl_options, [{cacertfile,"C:/Users/17126…

TensorFlow学习:在web前端如何使用Keras 模型

前言 在上篇文章 TensorFlow学习:使用官方模型进行图像分类、使用自己的数据对模型进行微调中我们学习了如何使用官方模型,以及使用自己的数据微调模型。 但是吧,代码一直是跑在Python里,而我本身是做前端开发的。我是很想让它在…

京东历史价格数据接口,京东商品历史价格接口,京东API接口

京东商品历史价格数据接口采集方法如下: 注册京东开发者账号,并创建应用,获取到应用ID(appID)、应用密钥(appSecret)以及访问令牌(accessToken)。获取接口请求地址。根据…

让 Visual Studio 用上 ChatGPT

一、简介 Visual chatGPT Studio 是 Visual Studio 的一个免费扩展,它直接在 IDE 中添加了 chatGPT 功能。它允许用户以可以根据菜单功能的方式使用 chatGPT。 二、功能介绍 该扩展提供了一组使用 ChatGPT 命令,可以在编辑器中选择你需要处理的代码或…

Python数据挖掘:入门、进阶与实用案例分析——自动售货机销售数据分析与应用

文章目录 摘要01 案例背景02 分析目标03 分析过程04 数据预处理1. 清洗数据1.1 合并订单表并处理缺失值1.2 增加“市”属性1.3 处理订单表中的“商品详情”属性1.4 处理“总金额(元)”属性 2.属性选择3.属性规约 05 销售数据可视化分析1.销售额和自动售货…

视频批量剪辑与分割:这些技巧帮你提高生成m3u8文件的效率

在数字媒体时代,m3u8文件已经成为了一种常见的流媒体格式,广泛应用于网络视频播放。这种文件由一系列音视频片段组成,对于提供高质量的视频体验至关重要。本文将介绍如何通过云炫AI智剪将视频批量剪辑与分割技巧来提高生成m3u8文件的效率&…

计算机网络第四层 运输层

一,运输层引入的目的 1,网络通信主体标识 网络通信的本质是运行的主机上的进程之间的通信 同一个主机上有多个进程在工作,进程如何加以区分标识(PID)---本地主机 网络上的主机需要一个统一的进程标识分配机制 逻辑…

基于单目相机的2D测量(工件尺寸和物体尺寸)

目录 1.简介 2.基于单目相机的2D测量 2.1 想法: 2.2 代码思路 2.2 主函数部分 1.简介 基于单目相机的2D测量技术在许多领域中具有重要的背景和意义。 工业制造:在工业制造过程中,精确测量是确保产品质量和一致性的关键。基于单目相机的2…

uniapp编译到小程序Component is not found in path “components/energy/illumination“

Component is not found in path "components/energy/illumination" 直接清除缓存重新编译

如何保护我们的网络安全

保护网络安全是至关重要的,尤其是在今天的数字化时代。以下是一些保护网络安全的基本步骤: 1、使用强密码:使用包含字母、数字和特殊字符的复杂密码。不要在多个网站上重复使用相同的密码。定期更改密码。 2、启用双因素认证 (2FA)&#xff…