06 - 数据收集 - 网络采集

随着互联网的快速发展,网络数据已成为重要的信息资源。我们需要通过网络来补充和完善知识库知识。

网络数据采集(Web Scraping)是指从网页中提取有用信息的过程。Python 凭借其丰富的库(如 RequestsBeautifulSoupScrapyselenium 等),成为网络数据采集的首选工具。

爬虫(crawler)也经常被称为网络蜘蛛spider),是按照一定的规则自动浏览网站并获取所需信息的机器人程序(自动化脚本代码),被广泛的应用于互联网搜索引擎和数据采集。

基本工作流程

  1. 确定目标网站

    在进行全网数据采集之前,首先需要确定目标网站。可以选择一些常见的搜索引擎、社交媒体等平台进行数据采集。对于一些需要登录才能访问的网站,可以使用 Selenium 等工具模拟登录。

  2. 选择合适的爬虫框架

    选择合适的爬虫框架可以大大提高数据采集效率。常用的爬虫框架有 ScrapyBeautiful SoupRequests等。其中 Scrapy 是一个功能强大且灵活的爬虫框架,支持异步处理和分布式部署;Beautiful Soup 则是一个 HTML / XML 解析器,可以方便地从 HTML 中提取数据;Requests 则是一个 HTTP 库,可以方便地发送 HTTP 请求和处理响应。

  3. 分析网页结构

    在进行数据采集之前,需要对目标网站的网页结构进行分析。可以使用 Chrome 浏览器的开发者工具或Firebug 等工具查看网页源代码,并确定需要采集的数据所在的位置和标签。

  4. 编写爬虫程序

    在确定目标网站和分析网页结构之后,可以开始编写爬虫程序。首先需要根据目标网站的 robots.txt 文件了解其爬取规则,然后根据自己的需求编写相应的爬虫程序。在编写过程中,需要注意反爬虫机制,可以设置User-AgentRefererHTTP 头信息来模拟浏览器行为,以及使用代理 IP 技术来规避 IP 封禁。

  5. 数据清洗和存储

    在完成数据采集之后,需要对采集到的数据进行清洗和整理。可以使用 pandas 等库将数据转换为DataFrame 格式,并进行数据清洗、去重、缺失值处理等操作。最后可以选择将数据存储到文件或数据库中。

  6. 多线程和分布式部署

    随着数据量的增加,单线程爬虫程序已经无法满足需求。可以使用多线程或协程技术来提高爬虫程序的效率。同时,分布式部署也是一个不错的选择,可以使用 Redis 等工具来实现分布式爬虫。

  7. 反爬虫机制

    为了防止被目标网站封禁 IP,需要注意反爬虫机制。可以使用随机 User-Agent、延时请求、代理 IP 等技术来规避反爬虫机制。同时也需要注意不要频繁地请求同一个页面,以免给服务器造成过大的负担。

  8. 常见问题和解决方案

    在进行数据采集时,常常会遇到各种问题,如网页乱码、无法获取数据等。这时候可以使用一些常见的解决方案,如设置编码方式、使用正则表达式等技术。

基本网络请求 - Requests

requests 是 Python 中最流行的 HTTP 客户端库,以简洁的 API 设计和强大的功能著称。帮我们轻松打开与外部世界交互的大门,无论是获取网页内容、与 API 交互,还是处理各种网络请求,requests 都能以它简洁而强大的方式为我们提供服务。

requests 模块是 Python 基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作。

request 构造方法

  • 输入参数

    • method: 指定 Http 的请求方法,可能值: GETOPTIONSHEADPOSTPUTPATCH, or DELETE

    • url: 指定请求的链接地址。

    • params: 【可选dict类型,请求参数字典,该参数值通过Query的方式传入 。

    • data:【可选dict 类型,请求参数字典,该参数值通过Body的方式传入。

    • json:【可选 】序列化的 JSON 格式对象,该参数值通过Body的方式传入。

    • headers:【可选dict 类型,设置请求头参数。

    • cookies: 【可选dictCookieJar 类型, 设置请求的 Cookie

    • files: 【可选dict 类型,其中字典的键是上传的参数名,键的值是一个上传文件对象或者上传文件元组:可以是二元组(filename, fileobj)或三元组(filename, fileobj, content_type)或四元组 (filename, fileobj, content_type, custom_headers) ;其中content_type 的值为 custom_headers,用来定义上传内容类型,附加到请求头的 content_type 中。

    • auth: 【可选 】 设置认证方法,以便启用 BasicDigest 或 其他自定义的认证方法。

    • timeout: 【可选float 或 一个三元组(connect timeout, read timeout) 定义请求的超时时间。

    • allow_redirects:【可选bool 类型,是否允许重定向,True为允许,默认为 True

    • proxies: 【可选dict 类型,设置代理地址。

    • verify: 【可选boolstr 类型;如果是布尔值,它确定我们是否验证服务器的 TLS 证书;如果是字符串,它必须是使用的 CA bundle的路径。默认为 True

    • stream: 【可选bool 型;如果设为 False,响应将以流的方式下载。

    • cert: 【可选str 类型或元组。如果是 str 类型,则表示指向 SSL 客户端证书文件路径;如果是原则,则是键值对(('cert', 'key'))。

  • 输出参数

    • Response 对象实例

get 方法

  • 输入参数

    • url: 指定请求的链接地址。

    • params: 【可选dict类型,请求参数字典,该参数值通过Query的方式传入 。

    • kewargs: 【可选dict 类型,参数键值对,可选的参数参见构造方法中的输入参数。

  • 输出参数

    • Response 对象实例

options 方法

  • 输入参数

    • url: 指定请求的链接地址。

    • kewargs: 【可选dict 类型,参数键值对,可选的参数参见构造方法中的输入参数。

  • 输出参数

    • Response 对象实例

head 方法

  • 输入参数

    • url: 指定请求的链接地址。

    • kewargs: 【可选dict 类型,参数键值对,可选的参数参见构造方法中的输入参数。

  • 输出参数

    • Response 对象实例

post 方法

  • 输入参数

    • url: 指定请求的链接地址。

    • data:【可选dict 类型,请求参数字典,该参数值通过Body的方式传入。

    • json:【可选 】序列化的 JSON 格式对象,该参数值通过Body的方式传入。

    • kewargs: 【可选dict 类型,参数键值对,可选的参数参见构造方法中的输入参数。

  • 输出参数

    • Response 对象实例

put 方法

  • 输入参数

    • url: 指定请求的链接地址。

    • data:【可选dict 类型,请求参数字典,该参数值通过Body的方式传入。

    • json:【可选 】序列化的 JSON 格式对象,该参数值通过Body的方式传入。

    • kewargs: 【可选dict 类型,参数键值对,可选的参数参见构造方法中的输入参数。

  • 输出参数

    • Response 对象实例

patch 方法

  • 输入参数

    • url: 指定请求的链接地址。

    • data:【可选dict 类型,请求参数字典,该参数值通过Body的方式传入。

    • json:【可选 】序列化的 JSON 格式对象,该参数值通过Body的方式传入。

    • kewargs: 【可选dict 类型,参数键值对,可选的参数参见构造方法中的输入参数。

  • 输出参数

    • Response 对象实例

delete 方法

  • 输入参数

    • url: 指定请求的链接地址。
    • kewargs: 【可选dict 类型,参数键值对,可选的参数参见构造方法中的输入参数。
  • 输出参数

    • Response 对象实例

应用案例

请求

假定我们要请求的链接是 https://latest.news.com,则:

复制代码
import requests
from lxml import etree

res  = requests.get("https://latest.news.com", headers={
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0"
})

内容抽取

请求成功后,我们来提取响应头:

复制代码
for head in res.headers:
        print(head, ":", res.headers[head])

结果:

复制代码
Date : Mon, 02 Jun 2025 04:30:18 GMT
Content-Type : text/html
Transfer-Encoding : chunked
Connection : keep-alive
Server : nginx
Content-Encoding : gzip
X-Via : 1.1 PS-CZX-01gfA163:7 (Cdn Cache Server V2.0), 1.1 PS-CZX-01YIQ141:12 (Cdn Cache Server V2.0), 1.1 PS-TSN-01fNz95:16 (Cdn Cache Server V2.0)
x-ws-request-id : 683d28da_PS-TSN-01fNz95_17318-41841

现在,我们开始来处理页面内容,数显将获取到响应重新编码(访问的站点返回的内容使用 gb2312 编码):

复制代码
res_text = res.text.encode(res.encoding).decode("gb2312")
root = etree.HTML(res_text)

解码后获取如下内容体(节选):

复制代码
<html lang="en">
<head>
    <meta charset="gb2312">
    <title>
        社会_
        新闻频道_中国青年网
    </title>
    ...
</head>
<body>
...
<ul>
   <li>
      <div class="title_txt">
         <p class="title">
             <a href="//news.youth.cn/sh/202506/t20250601_16034915.htm" target="_blank">这些年轻人去小镇当"戏漂"</a>
         </p>
         <span class="date fr">2025-06-01</span>
       </div>
    </li>
    <li>
       <div class="title_txt">
          <p class="title">
             <a href="//news.youth.cn/sh/202506/t20250601_16034914.htm" target="_blank">37个北大学生打造游戏:在鲜活的近现代史中感悟青春</a>
          </p>
          <span class="date fr">2025-06-01</span>
       </div>
     </li>
     <li>
        <div class="title_txt">
           <p class="title">
              <a href="//news.youth.cn/sh/202506/t20250601_16034913.htm" target="_blank">扰乱市场秩序 加大患病风险 警惕披上"甜蜜外衣"的五彩香烟</a>
            </p>
            <span class="date fr">2025-06-01</span>
         </div>
      </li>
      <li>
         <div class="title_txt">
            <p class="title">
               <a href="//news.youth.cn/sh/202505/t20250531_16034386.htm" target="_blank">河北武邑县一化工企业车间发生煮洗釜爆炸 已致5死2伤</a>
            </p>
            <span class="date fr">2025-05-31</span>
         </div>
      </li>
 </ul>          
...
</body>
</html>

为了方便,对返回的内容做了处理,只留下我们要操作的部分。现在我们来读取页面标题:

复制代码
# 获取标题
print("标题:", root.xpath('//title/text()'))

输出:

复制代码
标题: ['\n        社会_\n        新闻频道_中国青年网\n    ']

接着,我们来读取新闻列表:

复制代码
news = root.xpath('//p[@class="title"]/a')
    for item in news:
        print("新闻标题:", item.text)
        print("新闻链接:", item.get("href"))

输出:

复制代码
新闻标题: 这些年轻人去小镇当"戏漂"
新闻链接: //news.youth.cn/sh/202506/t20250601_16034915.htm
新闻标题: 37个北大学生打造游戏:在鲜活的近现代史中感悟青春
新闻链接: //news.youth.cn/sh/202506/t20250601_16034914.htm
新闻标题: 扰乱市场秩序 加大患病风险 警惕披上"甜蜜外衣"的五彩香烟
新闻链接: //news.youth.cn/sh/202506/t20250601_16034913.htm
新闻标题: 河北武邑县一化工企业车间发生煮洗釜爆炸 已致5死2伤
相关推荐
鲁邦通物联网5 小时前
边缘计算网关厂商的DevSecOps能力与固件维护体系评估
边缘计算·数据采集·工业数据采集·边缘计算网关·5g数采
数说故事6 小时前
有哪些采集游戏大数据的工具推荐?数说聚合提供全网游戏阵地数据
游戏·数据采集·用户洞察
夏日白云7 小时前
《PDF解析工程实录》第 8 章|融合策略:不是兜底,而是信息利用率最大化
pdf·llm·大语言模型·rag·文档解析
PascalMing8 小时前
Pascal.Edge物联网平台:生产企业设备数据采集与管理解决方案
物联网·c#·vue·数据采集
张彦峰ZYF9 小时前
持续改进 RAG 应用效果:从“能用”到“好用”的系统化方法
人工智能·rag·rag进阶
mubei-1239 小时前
FiD:利用具有生成模型的段落检索进行开放域问答
人工智能·llm·rag·检索增强生成
智联物联9 小时前
智慧交通高速公路隧道管理边缘计算网关应用方案
边缘计算·数据采集·远程监控·智慧交通·物联网应用·智能网关·隧道管理
沛沛老爹10 小时前
Web开发者实战AI Agent:基于Dify实现OpenAI Deep Research智能体
前端·人工智能·gpt·agent·rag·web转型
沛沛老爹10 小时前
Web开发者实战AI Agent:基于Dify的多模态文生图与文生视频智能体项目
前端·人工智能·llm·agent·rag·web转型