通过一学期对Python爬虫的学习我总结了以下几条心得:
首先,Python的学习与我们学过的C++完全不同。虽然C++与Python都是面向对象的高级程序设计语言,但是相较于C++,Python的编程十分简单。面对同样的问题,可能使用Python编程来进行实现所用的时间是使用C++的几分之一。
不过在运行效率上Python代码和C++最终都会变成CPU指令来跑,但一般情况下,比如反转和合并两个字符串,Python最终转换出来的CPU指令会比C++ 多很多。所以C++的运行效率远远高于Python。
其次,在学习爬虫之前,在我的心中觉得它是十分高深莫测,神乎其神的一种程序。但是通过老师一学期结合实际、突出实用、深入浅出的教学,我也自觉在逐渐揭开覆于其上的神秘面纱。通过一个个项目一个个实例的进行,我对爬虫的理解更加深刻。
说到我自己,我本身是一个很喜欢玩游戏的人,当我在课堂上听闻老师自写辅助程序,自己开设私服的“战绩”时,我好像找到了一条从未探寻过的路径。仔细回想,我们玩游戏只是在玩游戏,从来就没有想到过怎样“玩”游戏,而只是一直被游戏“玩”,这引燃了我对事物更深层次思考的引线,这可能是在这门课除了学到爬虫的部分技术之外,最大的收获。
总的来说,这门课的学习,带给我的是自身一种技能的提升,是对前沿数据技术的了解和使用,但更带给我的是思想之上的一些蜕变,人们总说要有一双“慧眼”来发现身边处处可见的美丽,而我想要用这样的注视,去在0与1二进制构成的数据里振翅遨游。
Pandas是一个开源的第三方Python库,从Numpy和Matplotlib的基础上构建而来,享有数据分析“三剑客之一”的盛名(NumPy、Matplotlib、Pandas)。Pandas已经成为Python数据分析的必备高级工具,它的目标是成为强大、灵活、可以支持任何编程语言的数据分析工具。
Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
Beautiful Soup已成为和lxml、html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度。
NumPy是Python语言的一个第三方库,其支持大量高维度数组与矩阵运算。此外,NumPy也针对数组运算提供大量的数学函数。机器学习涉及到大量对数组的变换和运算,NumPy就成了必不可少的工具之一。
Requests库是一个简洁且简单的处理HTTP请求的第三方库,它的最大优点是程序编写过程更接近正常URL访问过程。这个库建立在Python语言的urllib3库的基础上,类似这种在其他函数库之上再封装功能、提供更友好函数的方式在Python语言中十分常见。
在Python生态圈里,任何人都有通过技术创新或体验创新发表意见和展示才华的机会。requests库支持非常丰富的链接访问功能,包括国际域名和URL获取、HTTP长连接和连接缓存、HTTP会话和Cookie保持、浏览器使用风格的SSL验证、基本的摘要认证、有效的键值对Cookie记录、自动解压缩、自动内容解码、文件分块上传、HTTP(S)代理功能、连接超时处理、流数据下载等。
urllib是Python自带的标准库,无需安装,可以直接使用。它可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据。
SQLAlchemy分为两部分: ORM对象映射和核心的SQLexpression。ORM(Object Relational Mapping,对象关系映射)可以绕过SQL语句,把数据库的table(表)映射为编程语言的class(类),可以直接使用编程语言的对象模型操作数据库,而不使用SQL语句。
ORM把表映射成类,把行作为实例,把字段作为属性,在执行对象操作时最终会把对象的操作专函为数据库原生语句。
PyMySQL是在Python3.x版本中用于连接MySQL服务器的一个库。
PyMongo 是一个Python发行版,包含用于 MongoDB ,是从Python中使用MongoDB的推荐方法。
Gerapy自动提取器,可以使用此包来区分列表页面和详细信息页面,我们可以使用它从列表页面提取url,还可以从详细信息页面提取title,datetime,content,而无需任何XPath或Selector。 与其他方案相比,它对于中文新闻网站更有效。
pywin32是Python的一个代码库,包装了Windows 系统的 Win32 API,能创建和使用 COM 对象和图形窗口界面。如果你想用Python操控Windows系统,创建窗口、接受键鼠命令,或用到Win32 API,那你就需要它。
Scrapy,Python开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。
其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 后台也应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。
Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持。
Gerapy是一款分布式爬虫管理框架,支持Python 3,基于Scrapy、Scrapyd、Scrapyd-Client、Scrapy-Redis、Scrapyd-API、Scrapy-Splash、Jinjia2、Django、Vue.js开发,Gerapy可以帮助我们:更方便地控制爬虫运行,更直观地查看爬虫状态,更实时地查看爬取结果,更简单地实现项目部署,更统一地实现主机管理等。
import requests
from bs4 import BeautifulSoup
import pandas as pd
from urllib import parse
from sqlalchemy import create_engine
import pymysql
import pymongo
import json
首先,调用实验所需的数据包。
url = "http://health.people.com.cn/GB/408568/index.html"
html = requests.get(url)
html.encoding = "GB2312"
连接目标网站并对网站字符进行解码。
soup = BeautifulSoup(html.text,'lxml')
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"])
# url = "http://health.people.com.cn" + i.a["href"]
data.append((title,date,url))
调用BeautifulSoup包对目标网页数据进行爬取。
df = pd.DataFrame(data,columns=["title","date","url"])
将爬取数据转换成df数据并定义标题。
sql = 'insert into qiushi(title,date,url)values(%s,%s,%s) charset=utf8'
engine = create_engine('mysql+pymysql://root:20010911@localhost/test?charset=utf8')
df.to_sql('newslist', con=engine, if_exists='append')
用engine与mysql数据库连接,将数据插入到数据库。
client = pymongo.MongoClient('127.0.0.1',27017)
database = client["Mo"]
table = database["M"]
data_ = json. loads(df. T. to_json())
data_
连接本机MongoDB数据库并且建立数据库与集合。
table.insert_many(data_.values())
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()
使用import调用scrapy包。
创建文章标题title、发布日期date、文章链接url、站点site、文章正文content、栏目item等七类。
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}")
首先,生成一个middlewares,在其后面添加一个Header。之后调用scrapy包的useragent,以及中间件UserAgentMiddleware,之后读取配置,将其内的信息创建一个类。调取客户端列表之后,随机调取其一放进定义的user-Agent字段之中。最后在引擎之中使用这个类进行数据爬取。
settings = get_project_settings()
from itemadapter import ItemAdapter
# 添加必备包和加载设置
import pymongo
from scrapy.utils.project import get_project_settings
settings = get_project_settings()
class NewsdataPipeline:
def __init__(self):
host = settings["MONGODB_HOST"]
port = settings["MONGODB_PORT"]
dbname = settings["MONGODB_DATABASE"]
sheetname = settings["MONGODB_TABLE"]
client = pymongo.MongoClient(host=host, port=port)
# 指定数据库
mydb = client[dbname]
# 存放数据的数据库表名
self.post = mydb[sheetname]
def process_item(self, item, spider):
data = dict(item)
# 数据写入
self.post.insert_one(data)
return item
加载pymongo包,并加载其中的用户名、密码、IP、端口号、地址配置。
之后,定义一个类,与MongoDB进行链接,完成对数据库的链接。
在链接对应的数据库和表之后,使用dict函数定义一个data,再将爬取得到的数据导入到data当中。
若是MongoDB没有数据库和表则会在自动创建之后再进行写入,最后返回item之中。
BOT_NAME = 'NewsData'
SPIDER_MODULES = ['NewsData.spiders']
NEWSPIDER_MODULE = 'NewsData.spiders'
ROBOTSTXT_OBEY = False
DOWNLOADER_MIDDLEWARES = {
'NewsData.middlewares.RotateUserAgentMiddleware': 543,
}
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",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]
# 添加MONGODB数仓设置
MONGODB_HOST = "localhost" # 数仓IP
MONGODB_PORT = 27017 # 数仓端口号
MONGODB_DATABASE = "NewsData" # 数仓数据库
MONGODB_TABLE = "News_Process_A" # 数仓数据表单
代码1至13行:
设置机器的名称为NewsData;
创建爬虫文件的模板,设置爬虫文件的存储路径, 以将后来根据模板创建的文件存储在路径之中;
定义False即是不接受爬取站点的robot协议;
激活中间件middlewares以543的顺序加入DOWNLOADER_MIDDLEWARES之中;
设置pipeline字典为300。
之后代码则是将客户端信息存放在USER_AGENT_LIST。
添加对MongoDB的数仓设置:数仓IP为本地,数仓端口号为27017,数仓数据库为之前定义的NewsData,数据仓库表单为News_Process_A。
scrapy genspider new " "
启动之前先创建一个Python文件并打开。
import scrapy
from NewsData.items import NewsdataItem
from bs4 import BeautifulSoup
from gerapy_auto_extractor.extractors import *
from urllib import parse
class NewsSpider(scrapy.Spider):
name = 'news'
allowed_domains = []
start_urls = [
('https://shici.chazidian.com/gushidaquan/tangshi', '古诗大全', '唐诗三百首'),
#篇幅限制仅展示一条
]
def start_requests(self):
for url in self.start_urls:
item = NewsdataItem()
item["site"] = url[1]
item["item"] = url[2]
item["student_id"] = "20201914"
yield scrapy.Request(url=url[0], meta={"item": item}, callback=self.parse)
使用import调用scrapy包;加载NewsdataItem字典;加载相关的包;在scrapy框架之中定义一个类;name为’news’;allowed_domains定义为空;start_urls放入要爬取的目标网站(由于目标网站项目过长,只显示一条),准备工作完成。
从14行代码开始启动爬虫:使用for设置一个循环来爬取url,把url之中的第一位信息放入”site”,第二位信息放入”item”,学号20201914放入”student_id”,之后Re返回url之中的第0位信息,使用meta把”item”的值赋予到字典的”item”键当中,使用callback函数处理self.parse。
def parse(self, response):
item = response.meta["item"]
site_ = item["site"]
item_ = item["item"]
student_id_ = item["student_id"]
title_list = response.xpath('//div[@class="list100"]/ul/li/a/text()').extract()
url_list = response.xpath('//div[@class="list100"]/ul/li/a/@href').extract()
# print(url_list)
# date_list = response.xpath(
# '//*[@id="content-list"]/div/div[@class="txt"]/div[@class="info clearfix domPc"]/div[@class="time"]/text()').extract()
# item = response.meta["item"]
# print(item)
for each in range(len(title_list)):
item = NewsdataItem()
#item = response.meta["item"]
item["title"] = title_list[each]
item["url"] = "https://shici.chazidian.com" + str(url_list[each])
item["site"] = site_
item["item"] = item_
item["student_id"] = "20201914"
yield scrapy.Request(url=item["url"], meta={"item": item}, callback=self.parse_detail)
将字典item之中的”site”、”item”、”student_id”导入到定义的字段site_、item_、syudent_id当中,
之后使用response.xpath函数对url以及list进行模糊匹配,并将得到的匹配内容放入定义的字段title_list和url_list当中。
使用for定义一个循环,在循环中使用载入的NewsdataItem定义一个字典,将获取到的数据存储在字典中的”title”、”url”、”site”、”item”、”syudent_id”之中;
最后返回”url”,使用meta把”item”的值赋予到字典的”item”键当中,使用callback函数处理parse_detail。
def parse_detail(self, response):
item = response.meta["item"]
item["date"] = ""
strs = response.xpath('//div[@id="print_content"]').extract_first()
item["content"] = BeautifulSoup(strs, 'lxml').text
item["student_id"] = "20201914"
return item
编辑内容解析,首先使用response定义一个字典,解析meta[“item”];定义item[“date”]日期为空;
使用response.xpath对爬取的网页的正文内容进行解析,定义一个strs并将其放入;
使用BeautifulSoup对定义的strs进行解析,并将解析的内容放入item[“content”]当中,”20201914”放入到item[”student_id”]当中,返回item。
ITEM_PIPELINES = {
'NewsData.pipelines.NewsdataPipeline': 300,
}
MONGODB_HOST = "localhost" # 数仓IP
MONGODB_PORT = 27017 # 数仓端口号
MONGODB_DATABASE = "NewsData" # 数仓数据库
MONGODB_TABLE = "News_Process_A" # 数仓数据表单
class NewsdataPipeline:
def __init__(self):
host = settings["MONGODB_HOST"]
port = settings["MONGODB_PORT"]
dbname = settings["MONGODB_DATABASE"]
sheetname = settings["MONGODB_TABLE"]
# 创建MONGODB数据库链接
client = pymongo.MongoClient(host=host, port=port)
# 指定数据库
mydb = client[dbname] # 存放数据的数据库表名
self.post = mydb[sheetname]
然后编辑数据存储,代码1-8为4.1.4setting中的MongoDB设置。
代码10-20为采用自动创建数据库以及表单的方法,在4.1.3piplines(NewsdataPipline)中创建MongoDB数据库链接。
class NewsdataItem(scrapy.Item):
title = scrapy.Field() #文章标题
url = scrapy.Field() #文章链接
date = scrapy.Field() #发布日期
content = scrapy.Field() #文章正文
site = scrapy.Field() #站点
item = scrapy.Field() #栏目
student_id = “20201914”
随后如4.1.1item所写,将所有爬到的数据返回到”title”、”url”、”date”、”content”、”site”、”item”、”student_id”之中。
def process_item(self, item, spider):
data = dict(item)
self.post.insert_one(data)
return item
定义一个process_item,定义一个data,使用dict函数将item中的数据存入data,随后将定义的data导入到链接的MongoDB数据库之中。
scrapy crawl news
最后在cmd中启动爬虫。
conda create -n Gerapy python=3.9
在anaconda当中创建Python3.9环境。
conda activate Gerapy
启动创建好的gerapy环境。
pip install gerapy
pip install scrapy
pip install scrapyd
pip install pywin32
pip install gerapy_auto_extractor
使用pip安装各种所需模块。
cd C:\Users\Tattoo\AppData\Local\conda\conda\envs\Gerapy\gerapy
打开本机gerapy安装的目录,并在此目录下开启cmd;或在cmd中直接进入该目录。
gerapy init
初始化gerapy框架。
cd C:\Users\Tattoo\AppData\Local\conda\conda\envs\Gerapy\gerapy\gerapy
在cmd中进入上一步完成后创建的gerapy文件夹。
gerapy migrate
生成数据库。
gerapy initadmin
创建账户,账号密码为//admin admin。
gerapy runserver 0.0.0.0:8000
运行服务。
保持当前cmd开启状态,再打开一个cmd。
conda activate Gerapy
激活gerapy。
cd C:\Users\Tattoo\AppData\Local\conda\conda\envs\Gerapy\Scripts
进入本机anaconda下的Scripts目录。
scrapyd.exe
运行scrapyd.exe。
首先,开启浏览器,打开网页127.0.0.1:8000。
创建IP为127.0.0.1,端口号为6800的主机。
将项目都放进projects文件夹目录:C:\Users\Tattoo\AppData\Local\conda\conda\envs\Gerapy\gerapy\gerapy\projects
在项目管理中部署项目。
创建任务,爬虫名字本实验为shiyan,时区选择为Shanghai在主机管理中对部署的项目进行调度。
在主机管理中对部署的项目进行调度运行,运行结果如上
得到Navicat中mongodb数据库导入的表单。
网站爬取完成。