网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
通俗地讲,我们把互联网比作一张大蜘蛛网,每个站点资源比作蜘蛛网上的一个结点,爬虫就像一只蜘蛛,按照设计好的路线和规则在这张蜘蛛网上找到目标结点,获取资源。
在用户浏览网页的过程中,我们可能会看到许多好看的图片,比如 http://image.baidu.com/ ,我们会看到几张图片以及百度搜索框,类似下面图片这样:
这个过程其实就是用户输入网址之后,经过DNS服务器,找到服务器主机,向服务器发出一个请求,服务器经过解析之后,发送给用户的浏览器 HTML、JS、CSS 等文件,浏览器解析出来,用户便可以看到形形色色的图片了。
因此,用户看到的网页实质是由 HTML 代码构成的,爬虫爬来的便是这些内容,通过分析和过滤这些 HTML 代码,实现对图片、文字等资源的获取。
而本次报告将从人民网单个网页"http://health.people.com.cn/GB/408568/index.html"和健康时报网"http://www.jksb.com.cn/index.htm"多个网页进行爬取。
在学习爬虫之前只对爬虫有个概念性的认识。通过向服务器发送请求获取服务器传回信息,再根据其提取所需的信息。原理虽然简单,但是涉及的细节非常多,从一个坑爬出来又掉进另一个坑。
早在这门课程开启之前,我们学过一门课程叫做–Python数据仓库与数据挖掘。天真的我以为又是一门大致相同的课程,但随着课堂的深入,我逐渐对爬虫有了新的、更深刻的认识与理解。
首先,我先说明一下这门课程与众不同的教学方式:这门课程并没有像我们以往的那些编程语言课程一样,拿着书本去背很多的繁琐的概念。该课程老师带领我们直接上手操作,提前让我们了解以后工作的真实场景。这种授课方式极大的激发了我们的兴趣,调动了我们的积极性。
其次,在本学期学习中我渐渐了解到爬虫的学习并不是像表面那么简单,其中有很多细节和方法我们很容易忽略,起初我认为爬虫只是简单的调用一些包、库就能轻松爬取到数据,但是在实操中却出现了各种问题。比如在最初环境配置上、安装使用navicat、连接MongoDB数据库、第三方库安装上等,爬虫很多时候需要安装第三方库,但经常在安装成功后,程序并不能找到模块,原来我未在环境变量中添加pip的路径,这就等同于没有下载。当然解决了这些问题也只是跨入了爬虫学习的门槛。那时我天真的认为用第三方库或者现成的代码就能顺利爬到我想要的数据,随后的问题是为什么我的爬虫只能爬取一次,爬出来的结果和我打开的网页并不一样,可能会被有些网页监测到而进行伪装等。我才意识到原来爬虫并不是那么简单,要提前进行一些基础的学习并了解其整体流程而不是边写边问,事倍功半。
当然,在这两次的实验项目上我都出现了大大小小的问题。pycharm配置出现问题,老师告诉我换了社区版pycharm;Gerapy代码报错,老师给出了解决方案并进行细心地讲解;还有一些小的代码错误,直接一键百度也基本都能解决。所以,学习编程语言不能自己在那里死抠,要利用好周边的学习资源。老师也讲过他当时自学就走了很多弯路。所以,老师的存在以及百度让我在爬虫这条路上少走了很多弯路。而且,老师的课程还录制下来供我们观看,我的最后一次实验就是反复看老师录制的学习视频以及老师发布的学习文章一步一步完成的。
总之
不要急于求成,编程虽然不难,但也没有那么简单,不要想着速成,特别是对于计算机基础不是很好的人。
学习的过程中可能会遇到很多困难,或许会有很多你没有接触的东西冒出来,善用百度谷歌,一个个问题地解决,缺什么补什么。
对于初学者来讲,最重要的不是去学各种吊炸天的框架,追最新的技术。技术,框架是学不完的,永远都会层出不穷,最重要的是把基础学好。很多时候你有一个问题解决不了,都是你某些方面的知识缺了。慢慢来,不要急,随着学习的深入,再回过头来看以前的问题,会有豁然开朗的感觉。
一定要动手做,找点成就感,对你继续做下去有很大的促进作用。不然的话,遇到点困难很容易就放弃了。
pip模块 | 简介 |
---|---|
pandas | Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。 |
BeautifulSoup | beautifulsoup是一个解析器,可以特定的解析出内容,省去了我们编写正则表达式的麻烦。是一个可以从HTML或XML文件中提取数据的Python库。它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式。 |
numpy | NumPy是Python中科学计算的基础包。 它是一个Python库,提供多维数组对象,各种派生对象(如掩码数组和矩阵),以及用于数组快速操作的各种API,有包括数学、逻辑、形状操作、排序、选择、输入输出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等等。 NumPy包的核心是 ndarray 对象。 |
requests | requests是一个很实用的Python HTTP客户端库,编写爬虫和测试服务器响应数据时经常会用到,Requests是Python语言的第三方的库,专门用于发送HTTP请求 |
urllib | urllib库是Python内置的HTTP请求库。urllib模块提供的上层接口,使访问www和ftp上的数据就像访问本地文件一样。 |
pymysql | PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。 PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库。 |
pymongo | pymongo是python访问MongoDB的模块,使用该模块,我们定义了一个操作MongoDB的类PyMongoClient,包含了连接管理、集合管理、索引管理、增删改查、文件操作、聚合操作等方法。 |
scrapy | Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。 |
gerapy_auto_extractor | 是一个基于 Scrapy、Scrapyd 的分布式爬虫管理框架,自动提取器模块。 |
gerapy | 是一个分布式爬虫管理框架。能帮助我们:1. 更方便地控制爬虫运行 2. 更直观地查看爬虫状态 3. 更实时地查看爬取结果 4. 更简单地实现项目部署 5. 更统一地实现主机管理 |
Scrapyd | Scrapyd是一个用来部署和运行Scrapy项目的应用,由Scrapy的开发者开发。其可以通过一个简单的Json API来部署(上传)或者控制你的项目。 |
sqlalchemy | SQLAlchemy是 Python 编程语言下的一款开源软件。 提供了SQL工具包及 对象关系映射 (ORM)工具,使用 MIT许可证 发行。 |
selenium | Selenium是一个用于Web应用程序测试的工具。 |
流程描述:
1、 导入抓取与存储数据相关的库
2、 访问目标页面信息
3、 获取目标内容数据列表
4、 将数据列表转换成DataFrame形式
5、 连接Mysql数据库
6、 在Mysql数据库中创建存储数据的数据库和表
7、 将Dataframe形式数据存入表
8、 连接MongoDB数据库并创建数据库和表
9、 将Dataframe形式数据转化成Json格式
10、 将Json格式数据插入表中
11、最后两个库导入完成
import pandas as pd
import numpy as np
from pandas import DataFrame
import requests
from bs4 import BeautifulSoup
import pandas as pd
from urllib import parse
import pymysql
from sqlalchemy import create_engine
import sqlalchemy
import json
import pymongo
#调用数据包
url = "http://health.people.com.cn/GB/408568/index.html"
html = requests.get(url)
html.encoding = "GB2312"
#对爬取网站进行解码
soup = BeautifulSoup(html.text,'lxml')
list
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"])
print(title,date,url)
data.append((title,date,url))
#调用BeautifulSoup对该网页进行爬取
df = pd.DataFrame(data,columns=["title","date","url"])
df
#将爬取数据转换成df数据并定义标题
sql = 'insert into qiushi(title,date,url) values(%s,%s,%s) charset=utf8'
engine = create_engine('mysql+pymysql://root:123456@localhost/test1?charset=utf8')
df.to_sql( 'newlist1', con=engine, if_exists='append') #数据写入数据库
#运用sql、engine将数据写入数据库
client = pymongo.MongoClient('127.0.0.1',27017) #连接mongodb
database = client["NewsData"] #建立数据库
table = database["News"]
data_ = json.loads(df.T.to_json())
data_
#连接mongodb建立数据库建立集合并将爬取数据存入该集合
scrapy startproject NewsData
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
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()
# 添加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}")
# 添加必备包和加载设置
import pymongo
from scrapy.utils.project import get_project_settings
settings = get_project_settings()
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"]
# 创建MONGODB数据库链接
#client = pymongo.MongoClient(host=host, port=port, username=username, password=password)
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
将ROBOTSTXT_OBEY=True改为False
DOWNLOADER_MIDDLEWARES = {
#'NewsData.middlewares.NewsdataDownloaderMiddleware': 543,
'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_HOST = "localhost" # 数仓IP
MONGODB_PORT = 27017 # 数仓端口号
MONGODB_DATABASE = "NewsData" # 数仓数据库
MONGODB_TABLE = "News_Process_A" # 数仓数据表单
添加MONGODB数仓设置
我爬取的网站为:健康时报网
# -*- coding: utf-8 -*-
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'
page_link = set()
content_link = set()
allowed_domains = []
start_urls = [
('http://www.jksb.com.cn/html/news/knowledge/', '健康时报', '医药-新知', '20201896王瑚'),
('http://www.jksb.com.cn/html/news/industry/', '健康时报', '医药-产业', '20201896王瑚'),
('http://www.jksb.com.cn/html/news/hospital/', '健康时报', '医药-医院', '20201896王瑚'),
('http://www.jksb.com.cn/html/news/policy/', '健康时报', '医药-政策', '20201896王瑚'),
('http://www.jksb.com.cn/html/news/academic/', '健康时报', '医药-学术', '20201896王瑚'),
('http://www.jksb.com.cn/html/life/food/', '健康时报', '生活-饮食', '20201896王瑚'),
('http://www.jksb.com.cn/html/life/chinesemedicine/', '健康时报', '生活-中医', '20201896王瑚'),
('http://www.jksb.com.cn/html/life/nvxing/', '健康时报', '生活-女性', '20201896王瑚'),
('http://www.jksb.com.cn/html/life/baby/', '健康时报', '生活-婴幼', '20201896王瑚'),
('http://www.jksb.com.cn/html/life/sex/', '健康时报', '生活-两性', '20201896王瑚'),
('http://www.jksb.com.cn/html/growth/growthhot/', '健康时报', '生长发育-热点', '20201896王瑚'),
('http://www.jksb.com.cn/html/growth/growthnutrition/', '健康时报', '生长发育-营养', '20201896王瑚'),
('http://www.jksb.com.cn/html/growth/growthsport/', '健康时报', '生长发育-运动', '20201896王瑚'),
('http://www.jksb.com.cn/html/growth/growthmental/', '健康时报', '生长发育-心理', '20201896王瑚'),
('http://www.jksb.com.cn/html/growth/growthstory/', '健康时报', '生长发育-成长故事', '20201896王瑚'),
('http://www.jksb.com.cn/html/activities/focusing/', '健康时报', '活动-聚焦', '20201896王瑚'),
('http://www.jksb.com.cn/html/activities/review/', '健康时报', '活动-回顾', '20201896王瑚'),
('http://www.jksb.com.cn/html/supervision/exposure/', '健康时报', '监督-医药曝光', '20201896王瑚'),
('http://www.jksb.com.cn/html/supervision/consumer/', '健康时报', '监督-消费困惑', '20201896王瑚'),
('http://www.jksb.com.cn/html/supervision/domestic/', '健康时报', '监督-企业监督', '20201896王瑚'),
]
调用scrapy数据包,载入items文件中的newsdataitem字典,在载入上述相关的数据包
定义一个新的scrapy类,编辑项目名称,爬取网站链接放入start_urls中
在健康时报网找到需要爬取的网页url、title、content的xpath写入
def start_requests(self):
for url in self.start_urls:
item = NewsdataItem()
item["site"] = url[1]
item["item"] = url[2]
item["student_id"] = url[3]
yield scrapy.Request(url=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="left"]/ul/li//h1/a/text()').extract()
url_list = response.xpath('//div[@class="left"]/ul/li//h1/a/@href').extract()
date_list = response.xpath('//div[@class="info"]/span/text()').extract()
for each in range(len(title_list)):
item = NewsdataItem()
item["title"] = title_list[each]
#item["url"] = "https://www.msweekly.com/" + str(url_list[each])
item["url"] = url_list[each]
item["site"] = site_
item["item"] = item_
item["student_id"] = student_id_
item["date"] = date_list[each]
yield scrapy.Request(url=item["url"], meta={"item": item}, callback=self.parse_detail)
从目标网页进行检查,找出其中的title_list、url_list、date_list写入,并定义一个学号字段也写入其中
def parse_detail(self, response):
# data = extract_detail(response.text)
item = response.meta["item"]
strs = response.xpath('//div[@class="content"]').extract_first()
item["content"] = BeautifulSoup(strs, 'lxml').text
return item
next_url = response.xpath('//div[@id="page"]/a[last()]/@href').extract_first()
if next_url:
next_url = next_url
self.page_link.add(next_url)
yield scrapy.Request(next_url, meta={"item": item}, callback=self.parse)
这里因为爬的数据不够我添加了一段自动翻页代码。从目标网页检查里找到页码那一段url写入,从而实现自动翻页爬取。
def parse_detail(self, response):
item = response.meta["item"]
strs = response.xpath('//div[@class="content"]').extract_first()
item["content"] = BeautifulSoup(strs, 'lxml').text
return item
运用response对meta进行解析,定义一个字典item。将网页文章内容放到定义好的strs里,调用soup进行解析,解析完在放进定义的content中,最后返回item。
scrapy crawl news
在NewsData目录下利用powershell进行爬取
爬虫我们按照之前的内容写好了之后保证所有spider文件可以执行就可以了。接下来我们部署到远程的服务器上然后进行定时执行。
gerapy 安装
pip install gerapy
scrapyd 安装
pip install scrapyd
创建工作的文件目录,该目录下初始化项目用命令行执行
gerapy init
初始化数据库
cd gerapy
gerapy migrate
创建用户(默认用户名账号密码都是admin)
gerapy initadmin
然后就可以启动服务了,启动服务(可指定url和port)
gerapy runserver 0.0.0.0:8000
进入管理平台,浏览器输入"http://127.0.0.1.8000"
输入账号密码进入gerapy,进行主机管理设置
输入名称:localhost;ip:127.0.0.1;端口:6800,进行更新
更新后找到scrapyd.exe,在该目录下用命令行打开
将之前编辑好的NewsData文件放入到新文件夹中的projects里
下面进行项目部署
描述输入NewsData(注意不能是中文)点击重新打包
点击创建任务–输入名称–项目–爬虫–主机
调度方式我选择的inteval–1分钟爬一次,时区选择hongkong
最后点击创建
然后点击状态查看爬取进程