文章目录
个人主页:道友老李
欢迎加入社区:道友老李的学习社区
介绍
爬虫(Web Crawler 或 Web Spider)是一种自动化程序或脚本,它通过互联网上的链接从一个网页到另一个网页地抓取数据。爬虫通常用于搜索引擎索引、数据分析、内容聚合等目的。它们按照一定的规则遍历网页,下载页面内容,并将这些信息存储起来以供后续处理。
爬虫的工作原理
- 种子 URL:爬虫从一组初始的 URL(称为“种子”)开始。
- 获取页面:访问每个种子 URL,下载对应的网页内容。
- 解析页面:分析网页的 HTML 结构,提取有用的数据和所有指向其他页面的链接。
- 更新队列:将新发现的链接添加到待访问列表中,确保不会重复抓取已经访问过的页面。
- 存储数据:保存所提取的数据到数据库或其他形式的持久化存储中。
- 遵守规范:遵循网站的 robots.txt 文件和其他相关协议,尊重网站设定的爬行限制。
爬虫的主要类型
- 通用爬虫(General Purpose Crawlers):如谷歌、百度等搜索引擎使用的爬虫,目的是尽可能广泛地收集互联网上的信息,构建大型索引库。
- 聚焦爬虫(Focused Crawlers):专注于特定主题或领域的网页,比如只抓取与科技新闻相关的网站。
- 增量式爬虫(Incremental Crawlers):定期重新抓取已知页面,以捕捉任何更新或变化的内容。
- 深度优先搜索爬虫(DFS Crawlers):尽可能深地沿着一条路径前进,直到无法继续为止,然后回溯并选择另一条路径。
- 广度优先搜索爬虫(BFS Crawlers):先抓取同一层级的所有页面,再向下一层级扩展。
构建爬虫的技术栈
- 编程语言:Python 是最常用的语言之一,因为它有丰富的库支持,如 Scrapy、BeautifulSoup、Requests 等;此外,Java、JavaScript(Node.js)、Ruby 也有相应的框架。
- HTTP 请求库:例如 Python 的 Requests 库,用于发送 HTTP 请求并接收响应。
- HTML 解析器:如 BeautifulSoup、lxml,用于解析 HTML 文档结构,提取所需信息。
- 异步 I/O 和多线程:为了提高效率,可以使用异步 I/O 模型(如 asyncio)或多线程技术来并发处理多个请求。
- 数据库/文件系统:用来存储抓取下来的数据,可以选择关系型数据库(MySQL、PostgreSQL)、NoSQL 数据库(MongoDB)或者直接写入文件系统。
- 代理服务和 IP 轮换:为了避免被目标网站封禁 IP 地址,可以通过代理服务器分散请求来源,甚至动态更换 IP。
- 浏览器模拟工具:对于需要执行 JavaScript 渲染才能显示内容的网站,可以使用 Selenium、Puppeteer 等工具来模拟真实用户的浏览器行为。
爬虫的最佳实践
- 遵守法律和道德准则:确保你的爬虫活动符合法律法规,并且不侵犯个人隐私或版权。
- 尊重网站规则:检查并遵守目标网站的 robots.txt 文件中的指示,不要对服务器造成过大的负载。
- 设置合理的抓取频率:避免过于频繁地请求同一个站点,以免影响其正常运作。
- 处理异常情况:为网络故障、超时等问题设计好容错机制。
- 数据清洗和验证:确保抓取到的数据是准确无误的,并对其进行必要的清理和转换。
面临的挑战
- 反爬虫措施:许多网站会采取各种手段防止被恶意爬虫滥用,如验证码、登录验证、IP 黑名单等。
- 动态内容加载:随着 AJAX 和前端框架的发展,越来越多的网站采用异步加载方式,这增加了爬虫抓取完整页面内容的难度。
- 数据一致性:在分布式环境中,保证不同节点之间数据的一致性和准确性是一个复杂的问题。
总之,构建一个高效的爬虫需要综合考虑技术实现、性能优化以及伦理问题等多个方面。正确地设计和部署爬虫可以帮助我们更好地理解和利用互联网上的海量信息资源。
JSON文件存储
-
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它是基于ECMAScript的一个子集
-
JSON采用完全独立于语言的文本格式
-
JSON在Python中分别由list和dict组成。
Python中的json模块
json模块提供的4个功能
案例1
python">import jsons = '{"name":"张三"}'# 将字符串转成对象
obj = json.loads(s)
print(type(obj))
print(obj)# 将对象转成字符串类型
ss = json.dumps(obj, ensure_ascii=False)
print(type(ss))
print(ss)# 把对象(dict)保存到文件中
json.dump(obj, open('movie.txt', 'w', encoding='utf-8'), ensure_ascii=False)# 把文件中的内容读取到Python程序
obj2 = json.load(open('movie.txt', encoding='utf-8'))
print(obj2)
print(type(obj2))
案例2
python">import requests
import jsondef send_request():url = 'https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=7252335&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36'}resp = requests.get(url, headers=headers)return resp.textdef parse_json(data):return data.replace('fetchJSON_comment98(', '').replace(');', '') # 如果为str类型def type_change(data):return json.loads(data)def save(obj):json.dump(obj, open('京东销售最好的粽子数据.txt', 'w', encoding='utf-8'), ensure_ascii=False)def start():data = send_request()obj = parse_json(data)# print(type(type_change(s)))save(obj)# print(s)if __name__ == '__main__':start()
CSV文件
- 什么是CSV文件
- CSV是Comma Separated Values 称为逗号分隔值,以一种以.csv结尾的文件
- CSV文件的特点
- 值没有类型,所有值都是字符串
- 不能指定字体颜色等样式
- 不能指定单元格的宽高,
- 不能合并单元格
- 没有多个工作表
- 不能嵌入图像图表
CSV文件的操作
- 向CSV文件中写入数据
- 引入csv模块
- 使用open()函数创建 csv文件
- 借助csv.write()函数创建writer对象
- 调用writer对象的writerow()方法写入一行数据
- 调用writer对象的writerows()方法写入多行数据
- 从CSV文件中读取数据
- 引入csv模块
- 使用open()函数打开CSV文件
- 借助csv.reader()函数创建reader对象
- 读到的每一行都是一个列表(list)
案例1
python">import csvwith open('student.csv', 'a.txt+', newline='') as file:# 创建一个writer对象writer = csv.writer(file)# 一次写一行数据writer.writerow(['麻七', 23, 90])# 一次写入多行数据lst = [['Jack', 23, 98],['Marry', 22, 87],['Lili', 22, 76]]writer.writerows(lst)
案例2
python">import csvwith open('student.csv', 'r', newline='') as file:# 创建reader对象reader = csv.reader(file)for row in reader:print(row)
案例3
python">import requests
import json
import csvdef send_request():url = 'https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=7252335&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36'}resp = requests.get(url, headers=headers)return resp.textdef parse_html(data):s = data.replace('fetchJSON_comment98(', '').replace(');', '')dict_data = json.loads(s)comments_list = dict_data['comments']lst = []for comment in comments_list:content = comment['content'] # 评论的内容creationTime = comment['creationTime'].split(' ')[0] # 获取评论时间lst.append([content, creationTime])save(lst)def save(lst):with open('粽子的评论数据.csv', 'w', newline='') as file:writer = csv.writer(file)writer.writerows(lst)def start():data = send_request()parse_html(data)if __name__ == '__main__':start()
Excel文件
openpyxl模块
- 可以读取和写入Excel文件
- 需要单独安装,不包含有Python标准模块里
- 处理Excel数据
- 处理Excel公式
- 处理Excel样式
- 在表格内插入图表
操作Excel文件
-
向Excel文件中写入数据
- 创建工作薄对象 openpyxl.Workbook()
- 获取活动工作表对象 wb.active
- 获取单元格 sheet[单元格名称]
- 向单元格中写入数据 cell.value=值
- 向Excel中写入一行数据sheet.append(列表)
- 保存Excel文件 wb.save(文件)
-
从Excel中读取数据
- 加载工作薄对象 openpyxl.load_workbook(文件名)
- 获取活动工作表对象 wb.active
- 获取单元格 sheet[单元格名称]
- 获取单元格的值 cell.value
- 获取一系列格子 sheet[‘A’],sheet[3],sheet[‘A:C’]
- 获取整个表格的所有行 sheet.rows
案例1
向Excel写入数据
python">import openpyxl# 创建工作薄对象
wb = openpyxl.Workbook()
# 获取工作表sheet
sheet = wb.active
# 获取指定的单元格
cell = sheet['A1']
# 向单元格中写数据
cell.value = '中国美丽'# 一次写入一行数据
lst = ['姓名', '年龄', '成绩']
sheet.append(lst)# 向Excel文件中一次写入多行数据lst2 = [['张三', 22, 90],['李四', 21, 100],['王五', 23, 97]
]
for row in lst2:sheet.append(row)
# 保存
wb.save('我的Excel文件.xlsx')
案例2
从Excel读取数据
python">import openpyxl# 加载Excel文件(创建一个Python中的工作薄对象)
wb = openpyxl.load_workbook('销售数据.xlsx')# 获取工作表对象
# sheet=wb.active
sheet = wb['Sheet']# 获取指定的单元格
cell = sheet['A1']
# 获取指定的单元格中的内容
value = cell.value
print(value)# 获取一系列的格子
columns = sheet['A']
for col in columns: # 获取A列中的每一个单元格print(col.value) # 获取A列中每一个单元格中的值
# print(columns)
print('----------------------------------------------------')
row = sheet[3]
for cell in row: # 获取第三行的每一个单元格print(cell.value) # 获取第三行的每一个单元格的值
# print(row)
print('--------------------------------------------------------')
cols = sheet['B:C']
for col in cols: # 获取每一列for cell in col: # 获取每一个列中的单元格print(cell.value) # 获取每一个单元格的值print('------------------------------------')
案例3
python">import requests
from bs4 import BeautifulSoup
import openpyxldef send_request():url = 'http://www.xiachufang.com/explore/'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36'}resp = requests.get(url, headers=headers)return resp.textdef parse_html(html):# 解析数据count = 0bs = BeautifulSoup(html, 'lxml')lst_name = bs.find_all('p', class_='name')lst_category = bs.find_all('p', class_='ing ellipsis')# print(lst_name)# print(lst_category)lst = []for i in range(len(lst_name)):count += 1food_url = 'http://www.xiachufang.com/' + lst_name[i].find('a.txt')['href']# print(food_url)lst.append([count, lst_name[i].text[18:-14], lst_category[i].text[1:-1], food_url])# print(lst)save(lst)def save(lst):wb = openpyxl.Workbook()sheet = wb.activefor row in lst:sheet.append(row)wb.save('下厨房美食.xlsx')def start():result = send_request()parse_html(result)if __name__ == '__main__':start()