Python爬虫总结——从基础爬虫到Scrapy+Gerapy部署网络爬虫
前言
网络爬虫(也称为网页蜘蛛、Web 蜘蛛、网络机器人或网络蚂蜂)是一种自动按照特定规则在网络上搜索信息的软件程序。网络爬虫的主要目的是扫描网络,收集信息,并将其存储在数据库或其他存储系统中。网络爬虫可以用于多种目的,例如搜索引擎中收集网站内容以供搜索、监测网站的变化、网站访问统计、收集电子邮件地址等。本文通过jupyter notebook上进行基础单网页爬虫以及通过Scrapy+Gerapy实现多网页爬虫、定时抓取网页信息的案例演示。
一、常用pip模块介绍
1.NumPy库
NumPy是一个Python库,用于在Python中进行科学计算。它提供了许多用于在数组和矩阵中进行高效计算的函数。它还提供了许多用于对数组进行处理和变换的工具。安装方法:
pip install numpy
2.Pandas库
Pandas是一个用于数据处理和分析的流行Python库。它提供了有效存储大型数据集的数据结构和使用这些数据集的工具。安装方法:
pip install pandas
3.Requests库
基于 urllib 编写的,阻塞式 HTTP 请求库,发出一个请求,一直等待服务器响应后,程序才能进行下一步处理。安装方法:
pip install requests
4.BeautifulSoup库
BeautifulSoup 是一个 Python 库,可以方便地解析 HTML 和 XML 文档。它可以帮助你提取所需的数据,并组织成可读性较好的形式,是BS4库中的解析器组件。安装方法:
pip install beautifulsoup4
5.parse库
parse是一个用于解析字符串和数据的Python库。它提供了一组函数,用于从各种类型的输入中提取数据,并将其转换为结构化数据类型,如列表、字典和对象。安装方法:
pip install parse
6.PyMongo库
一个用于直接连接 mongodb 数据库进行查询操作的库。安装方法:
pip install pymongo
7.Scrapy库
这是一个功能强大的爬虫框架,可以帮助你快速开发爬虫应用。它提供了丰富的 API 和工具,可以帮助你更方便地处理爬取的任务,并且提供了很多方便的功能,如链接跟踪、数据提取、自动下载中间件等,使用 Scrapy 可以快速地开发出功能强大的爬虫。安装方法:
pip install scrapy
8.urllib库
urllib是一个用于处理URL的Python库。它提供了一组用于执行常见任务的函数,如发送HTTP请求、解析URL以及编码和解码数据。安装方法:
pip install urllib
9.lxml库
一个用来解析和处理 XML 和 HTML 的库,可以作为 Beautiful Soup 的替代选择。安装方法:
pip install lxml
10.pywin32库
pywin32 是一个 Python 的扩展库,用来在 Python 中使用 Windows 的 API。它可以让你在 Python 中调用 Windows 系统的功能,如操作系统信息、系统服务、注册表等。安装方法:
pip install pywin32
11.Scrapyd库
Scrapyd 是一个用来部署和管理 Scrapy 爬虫的 Python 库。使用 Scrapyd 可以将 Scrapy 爬虫部署到服务器上,并提供了一系列的 API,用来管理和调用爬虫。Scrapyd 可以帮助你实现分布式爬虫,并且支持调度和监控爬虫的运行状态。安装方法:
pip install scrapyd
12.Gerapy库
Gerapy是一个用于构建爬虫项目的Python库。它提供了一个简单的界面,可以让用户使用各种方式编写爬虫,并支持多种数据存储后端(如MongoDB、Elasticsearch等)。Gerapy还可以自动扩展爬虫,支持分布式爬取和数据提取,并可以通过API与其他系统集成。安装方法:
pip install gerapy
13.gerapy_auto_extractor包
Gerapy Auto Extractor是Gerapy中的一个功能,可以自动提取网页中的数据。它使用了基于模板的数据提取方法,即用户需要提供一个模板,指示Gerapy Auto Extractor如何从网页中提取数据。Gerapy Auto Extractor使用XPath表达式来描述如何从网页中定位元素,并使用正则表达式来提取数据。Gerapy Auto Extractor可以与Gerapy的其他功能集成,并支持分布式爬取和数据提取。安装方法:
pip install gerapy_auto_extractor
14.SQLAlchemy库
SQLAlchemy是一个流行的Python库,它为与数据库交互提供了一个很好的API。它设计得灵活而强大,可以支持多种数据库后端,包括MySQL、PostgreSQL、Oracle等。安装方法:
pip install sqlalchemy
15.Selenium库
Selenium是一个用于自动化Web浏览器的开源库。它可以用来模拟用户在浏览器中执行的操作,如点击链接、填写表单、执行JavaScript脚本等。Selenium支持多种浏览器,包括Chrome、Firefox、Safari等。它的主要优势在于它可以在不同的浏览器、操作系统和设备上运行,这使得它成为自动化测试的首选工具。安装方法:
pip install selenium
16.BS4库
BS4是一个完整的库,包含了多个组件,可以用于解析、查找、修改HTML和XML文档。安装方法:
pip install bs4
二、案例一:使用jupyter notebook爬取数据并存储在MySQL数据库和mongoDB数据库中
1.导入函数库
import requests
import pandas as pd
from bs4 import BeautifulSoup
from urllib import parse
from sqlalchemy import create_engine
import pymongo
import pymysql
2.链接目标网站并进行内容的解析
url = "http://health.people.com.cn/GB/408568/index.html"
html = requests.get(url) #向服务器请求数据,服务器返回的结果是个Response对象
html.encoding = "GB2312" #根据网站的编码模式进行编码,避免出现乱码
soup = BeautifulSoup(html.text,'lxml') #使用lxml进行网站内容的解析
3.爬取网站中需要的数据
data = []
#使用for循环爬取网站中所有class名为newsItems的div标签中的标题、日期与网址并存储在data列表中
for i in soup.find_all("div",class_="newsItems"):
title = i.a.text
date = i.div.text
url =parse.urljoin(url,i.a["href"])
data.append((title,date,url))
#将data转换成表格形式存储在df中
df = pd.DataFrame(data,columns=["title","date","url"])
4.链接mongoDB数据库
#建立连接,创建一个类,传入参数为数据库服务的ip地址和端口
client = pymongo.MongoClient('127.0.0.1',27017)
database = client["NewsData"] #通过创建的数据对象获取数据库对象,数据库名为NewsData
table = database["News"] #通过数据库对象获取集合对象,集合名为News
5.存储数据到mongoDB数据库
import json
data_ = json.loads(df.T.to_json()) #将df由表格类型转换成json类型再转换成字典类型
table.insert_many(data_.values()) #将data_数据插入到表中
结果如图所示
6.链接MySQL数据库
(1)方法一
#使用pymsql.connect函数链接数据库,参数分别为服务器地址,数据库用户名,数据库密码,数据库
db = pymysql.connect(host='localhost',user='root',password='root', database='mysql')
(2)方法二
#使用create_engine链接数据库,参数为create_engine(数据库类型+数据库驱动选择://数据库用户名:用户密码@服务器地址:端口/数据库)
engine = create_engine("mysql+pymysql://root:root@localhost:3306/mysql?charset=utf8mb4")
7.存储数据到MySQL数据库
#使用.to_sql()函数存储数据至MySQL数据库
df.to_sql('newlist',engine,schema='mysql',if_exists='append',index=False,index_label=False)
结果如图所示
三、案例二:使用Scrapy部署网络爬虫爬取并存储数据到mongoDB数据库
1.Scrapy爬虫框架初始化
(1)生成原始框架
在命令行(cmd)中输入
scrapy startproject NewsData
结果如图所示
(2)item.py文件配置
import scrapy
class NewsdataItem(scrapy.Item):
title = scrapy.Field() #文章标题
url = scrapy.Field() #文章链接
date = scrapy.Field() #发布日期
content = scrapy.Field() #文章正文
site =scrapy.Field() #站点
item = scrapy.Field() #栏目
student_id = scrapy.Field() #学号
(3)middleware.py文件配置
#添加Header和IP类
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
from scrapy.utils.project import get_project_settings
import random
settings = get_project_settings()
class RotateUserAgentMiddleware(UserAgentMiddleware):
def process_request(self, request, spider):
referer = request.url
if referer:
request.headers["referer"] = referer
USER_AGENT_LIST = settings.get('USER_AGENT_LIST')
user_agent = random.choice(USER_AGENT_LIST)
if user_agent:
request.headers.setdefault('user-Agent', user_agent)
print(f"user-Agent:{user_agent}")
(4)pipelines.py文件配置
# 添加必备包和加载设置
import pymongo
from scrapy.utils.project import get_project_settings
settings = get_project_settings()
class NewsdataPipeline:
# class中全部替换
def __init__(self):
#以下MONGODB_的值在setting.py文件中进行
host = settings["MONGODB_HOST"]
port = settings["MONGODB_PORT"]
dbname = settings["MONGODB_DATABASE"]
sheetname = settings["MONGODB_TABLE"]
#表示数据库的用户和密码,若无可注释掉
#username = settings["MONGODB_USER"]
#password = settings["MONGODB_PASSWORD"]
client = pymongo.MongoClient(host=host, port=port) # 创建MONGODB数据库链接
mydb = client[dbname] # 指定数据库
self.post = mydb[sheetname] # 存放数据的数据库表名
def process_item(self, item, spider):
data = dict(item)
# 数据写入
self.post.insert_one(data)
return item
(5)settings.py文件配置
将机器人协议设置为False,拒绝遵守机器人协议,防止因为爬取内容不符合该协议时遭到拒绝
ROBOTSTXT_OBEY = False
设置下载中间件
DOWNLOADER_MIDDLEWARES = {
#'NewsData.middlewares.NewsdataDownloaderMiddleware': 543,
'NewsData.middlewares.RotateUserAgentMiddleware': 543,
}
#RotateUSerAgent为middleware.py文件中定义的class类函数名
设置项目管道
ITEM_PIPELINES = {
'NewsData.pipelines.NewsdataPipeline': 300,
}
设置用户代理
提示: 仅展示部分代理
USER_AGENT_LIST = [
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
]
设置mongoDB数据仓库
MONGODB_HOST = "localhost" # 数仓IP
MONGODB_PORT = 27017 # 数仓端口号
MONGODB_DATABASE = "NewsData" # 数仓数据库
MONGODB_TABLE = "News_Process_A" # 数仓数据表单
2.创建爬虫python文件
(1)生成爬虫文件
NewsData目录中打开终端输入一下命令
scrapy genspider news " "
" "表示为目标引用的作用域,此处没有定义,默认全域
在spiders目录下生成news.py文件
(2)导入函数库
import scrapy
from NewsData.items import NewsdataItem
from bs4 import BeautifulSoup
(3)更改初始class类
提示:仅展示部分爬取地址
class NewsSpider(scrapy.Spider):
name = 'news'
allowed_domains = []
start_urls = [
('https://www.sanwen.org.cn/sw/', '散文网', '经典散文', '20201903'),
('https://www.sanwen.org.cn/sw/mingjiasanwen', '散文网', '名家散文', '20201903'),
('https://www.sanwen.org.cn/sw/yingyusanwen/', '散文网', '英语散文', '20201903'),
('https://www.sanwen.org.cn/sw/gudaisanwen/', '散文网', '古代散文', '20201903'),
('https://www.sanwen.org.cn/sw/jierisanwen/', '散文网', '节日散文', '20201903'),
('https://www.sanwen.org.cn/sw/jishisanwen/', '散文网', '记事散文', '20201903'),
('https://www.sanwen.org.cn/sw/xierensanwen/', '散文网', '写人散文', '20201903'),
('https://www.sanwen.org.cn/sw/xiewusanwen/', '散文网', '写物散文', '20201903'),
('https://www.sanwen.org.cn/sw/sanwenshi/', '散文网', '散文诗', '20201903'),
('https://www.sanwen.org.cn/sw/xiejingsanwen/', '散文网', '写景散文', '20201903'),
('https://www.sanwen.org.cn/sw/zhelisanwen/', '散文网', '哲理散文', '20201903'),
('https://www.sanwen.org.cn/sw/qinggansanwen/', '散文网', '情感散文', '20201903'),
('https://www.sanwen.org.cn/sw/shanggansanwen/', '散文网', '伤感散文', '20201903'),
]
其中news为spider名,start_url列表中存放待爬取网页链接、站点名等信息
(4)定义爬虫启动函数start_requests
def start_requests(self):
for url in self.start_urls:
item = NewsdataItem() # 调用item.py中定义的NewsdataItem函数,创建一个item字典
item["site"] = url[1] # item["site"]读取每次读取的self.start_urls中每一项的第二个元素
item["item"] = url[2] # item["item"]读取每次读取的self.start_urls中每一项的第三个元素
item["student_id"] = url[3] # item["student_id"]读取每次读取的self.start_urls中每一项的第四个元素
# 调用parse函数,返回的参数分别是每次读取的self.start_urls中每一项的第一个元素和新的item字典
yield scrapy.Request(url=url[0], meta={"item": item}, callback=self.parse)
(5)定义列表解析函数parse
如图可以发现栏目的名称和网址可以在class类名为tj-news的div标签下的h4标签下的a标签里title和href确定
def parse(self, response):
item = response.meta["item"] #将传入的item参数存入到同名item字典里
site_ = item["site"] #将item字典里的site存入到变量site_里
item_ = item["item"] #将item字典里的item存入到变量item_里
student_id_ = item["student_id"] #将item字典里的student_id存入到变量student_id_里
#通过模糊匹配爬取栏目和网址,xpath值如上图所示
title_list = response.xpath('//div[@class="tj-news"]/h4/a/@title').extract()
url_list = response.xpath('//div[@class="tj-news"]/h4/a/@href').extract()
#使用for循环爬取每个栏目下第一页各文章的内容
for each in range(len(title_list)):
item = NewsdataItem()
item["item"] = item_
item["title"] = title_list[each]
item["url"] = "https://www.sanwen.org.cn" + str(url_list[each]) #将相对地址改写成绝对地址
item["site"] = site_
item["student_id"] = student_id_
#调用parse_detail函数,传入的参数分别为item字典中的url字段,以及新的item字典
yield scrapy.Request(url=item["url"], meta={"item": item}, callback=self.parse_detail)
(6)定义内容解析函数parse_detail
def parse_detail(self, response):
item = response.meta["item"] #将传入的item存入一个新的item字典
#模糊匹配文章的内容,方法同上
strs = response.xpath('//div[@class="article"]').extract_first()
item["content"] = BeautifulSoup(strs, 'lxml').text #解析获取的文章内容并存入item["content"]
return item
3.存储数据至mongoDB数据库
在settings.py进行进行如下设置
ITEM_PIPELINES = {
'NewsData.pipelines.NewsdataPipeline': 300,
}
# 添加MONGODB数仓设置
MONGODB_HOST = "localhost" # 数仓IP
MONGODB_PORT = 27017 # 数仓端口号
MONGODB_DATABASE = "NewsData" # 数仓数据库
MONGODB_TABLE = "News_Process_A" # 数仓数据表单
在pipelines.py进行如下设置
class NewsdataPipeline:
# class中全部替换
def __init__(self):
host = settings["MONGODB_HOST"]
port = settings["MONGODB_PORT"]
dbname = settings["MONGODB_DATABASE"]
sheetname = settings["MONGODB_TABLE"]
#username = settings["MONGODB_USER"]
#password = settings["MONGODB_PASSWORD"]
client = pymongo.MongoClient(host=host, port=port) # 创建MONGODB数据库链接
mydb = client[dbname] # 指定数据库
self.post = mydb[sheetname] # 存放数据的数据库表名
def process_item(self, item, spider):
data = dict(item)
self.post.insert_one(data) # 数据写入
return item
mongoDB数据库中结果如图所示
四、案例三:使用Gerapy进行定时爬取并存储数据到mongoDB数据库
1.Scrapyd服务启动
安装scrapyd库
pip install scrapyd
启动scrapyd.exe
使用Everthing软件进行全盘检索scrapyd.exe文件,然后在该目录下启动终端
scrapyd.exe
2.Gerapy服务启动
安装gerapy库
pip install gerapy
创建一个文件夹,命名为gerapy
在该目录下使用终端输入
gerapy init
进入生成的gerapy文件夹
输入如下指令进行数据迁移
gerapy migrate
初始化超级用户
geray initadmin
启动gerapy服务(注意,若使用8000端口需要关闭酷狗)
gerapy runserver 0.0.0.0:8000
3.使用Gerapy进行定时任务爬取
(1)登录Gerapy
在浏览器中输入127.0.0.1:8000或http://localhost:8000进入登录界面,初始化超级用户后账号密码皆为admin
(2)创建主机
在主机管理中点击创建进入如下界面
根据主机的IP和端口填写内容即可,结果如下图所示
(3)创建项目与部署
将案例二中编写的Scrapy文件,即NewsData目录复制到geray目录下的project文件夹中,项目管理界面如下图所示
对该项目进行部署
在打包项目中成功打包之后在部署项目选取一个或多个主机进行部署
(4)创建任务
此处名称是任务名称,项目名字需为project中存在的项目名,爬虫为选取项目的spider名称,主机为当前创建过的主机,调度方式表示任务自动执行的周期情况
下图为任务成功执行后的状态
mongoDB数据库存储结果如下图所示
(5)小组分布式爬虫展示
打包部署完成后的五个项目
设置定时爬取任务
mongoDB数据库存储结果
查字典诗词网爬取数据结果
出国留学网-散文爬取数据结果
民生网爬取数据结果
散文网爬取数据结果
新民网爬取数据结果