环境准备:
python3.7
Pycharm
Scrapy框架
注:全部源代码会在文章最后给出
理论概述:
什么是Scrapy框架?
Scrapy是一个快速、高层次、轻量级的屏幕抓取和web抓取的python爬虫框架
Scrapy的用途?
Scrapy用途非常广泛,主要用于抓取特定web站点的信息并从中提取特定结构的数据,除此之外,还可用于数据挖掘、监测、自动化测试、信息处理和历史片段(历史记录)打包等
目标网址:
环境搭建:
一、安装Scrapy
安装Scrapy的方式有两种:
A、使用Anaconda进行安装
B、使用pip安装
注:使用Anaconda安装Scrapy需要已经安装好Anaconda才能继续安装Scrapy,使用pip安装需要先下载Twisted插件,直接安装scrapy是会报错的,笔者推荐使用Anaconda进行安装
1、使用Anaconda安装:
conda install scrapy
2、使用pip安装:
A:安装Twisted:
windows 64位及python3.7版本https://download.csdn.net/download/m0_54925305/59579598?spm=1001.2014.3001.5503
https://download.csdn.net/download/m0_54925305/59579598?spm=1001.2014.3001.5503
其余版本下载链接https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
进入终端:
pip install Twisted文件名 再 pip install scrapy
安装成功后的效果,终端输入scrapy:
二、创建 beijingbus 的scrapy项目
1、进入pycharm的终端创建scrapy项目
2、进入创建的beijingbus目录
3、创建一个spider
三、搭建scrapy项目
项目主体架构:
功能描述:
beijingbus/spiders/:放置spider代码的目录,用于编写用户自定义的爬虫
beijingbus/items.py:项目中的item文件,用于定义用户要抓取的字段
beijingbus/middlewares.py:主要是对功能的拓展,用于用户添加一些自定义的功能
beijingbus/pipelines.py:管道文件,当spider抓取到内容(item)以后,会被送到这里,这些信息在这里会被清洗,去重,保存到数据库等
beijingbus/settings.py:项目的设置文件,配置的默认功能在这里存放
1、进入settings.py将ROBOTSTXT_OBEY的参数改为False,目的是使其不遵守Robots协议
2、将DEFAULT_REQUEST_HEADERS方法注释掉,并在其中添加User-Agent属性,代码如下
注:此操作的功能是使爬虫实现模拟浏览器访问的效果
3、进入bei_bus.py文件,对start_urls进行修改,代码如下图
4、新建一个start_requests()方法(此方法名固定),获得并构建一级网页URL,代码如下
def start_requests(self): #这里的循环可以根据实际情况自行修改,这里不想全部爬取,只要list1下的就可以,故循环执行一次 #start_requests()方法使用 format 拼接 URL,并用 yield 再次发起网页访问, callback 后的方法为回调函数,可以在回调函数中对网页进行处理。 for page in range(1): url = '{url}/list{page}'.format(url=self.start_urls, page=(page + 1)) yield FormRequest(url, callback=self.parse_index)
5、在pycharm中的命令行界面执行 "scrapy crawl bei_bus" 爬取一级网页,效果如下进入beijingbus/目录下执行 "scrapy crawl bei_bus"命令
注:scrapy框架爬虫开始执行
一级网页效果:
6、 爬取二级网页
def parse_index(self, reponse): beijing = reponse.xpath('//div[@class="list clearfix"]/a//@href').extract() for c in beijing: url3 = urljoin(self.start_urls, c) yield Request(url3, callback=self.parse_detail)
进入命令行界面执行 "scrapy crawl bei_bus" 爬取二级网页,效果如图
注:在parse_index()方法中,使用Xpath寻找详细信息页面的URL,并对网址进行拼接,之后对二级网页发起请求,并返回回调函数parse_detail()
7、爬取页面详细信息
def parse_detail(self, response): #这里只爬取这些字段,可以自行添加 a = response.xpath('//h1[@class="title"]/text()').extract_first() b = response.xpath('//a[@class="category"]/text()').extract_first() c = response.xpath('//ul[@class="bus-desc"]/li[1]/text()').extract_first() item = BeijingbusItem() for field in item.fields: item[field] = eval(field) yield item
8、详细信息页面效果
注:这将会爬取到list1标签内所有路信息,其中包括公交路线,市区普线,运行时间这些字段,其余字段可以自行添加。
9、将爬取的内容存入Mysql
A、在 MySQL 的 studb 数据库中创建一个 businfo 表:
create table businfo( a varchar(1000), b varchar(1000), c varchar(1000));
B、在 settings.py 文件末尾添加如下参数:
DB_HOST = 'localhost' DB_USER = 'root' DB_PWD = 'dang' DB_CHARSET='UTF8' DB = 'studb'
C、在 pipelines.py 文件中,修改 class 名称为 MySQL Pipeline,添加初始化方法,将 host、user、password、db、charset 从 settings 中读取出来,并通过添加一个connect()方法建立与数据库的连接,代码如下。
import pymysql from itemadapter import ItemAdapter from beijingbus import settings class MysqlPipeline(object): def __init__(self): self.host = settings.DB_HOST self.user = settings.DB_USER self.pwd = settings.DB_PWD self.db = settings.DB self.charset = settings.DB_CHARSET self.connect() def connect(self): self.conn = pymysql.connect(host=self.host, user=self.user, password=self.pwd, db=self.db, charset=self.charset) self.cursor = self.conn.cursor() def process_item(self, item, spider): sql = 'INSERT INTO businfo (a,b,c)VALUES("%s","%s","%s")' % (item['a'], item['b'], item['c']) self.cursor.execute(sql) self.conn.commit() return item def close_spider(self, spider): self.conn.close() self.cursor.close()
注:close_spider()方法,用于关闭 MySQL 数据库连接,process_item()方法,用于完成向数据库中插入数据的操作
D、在 settings.py 中将 ITEM_PIPELINES 方法的注释去掉,并将其中的内容 改为“'beibus.pipelines.MysqlPipeline':300”,后面的数字代表优先级,数字越小, 优先级越高,代码如下:
ITEM_PIPELINES = { 'beijingbus.pipelines.MysqlPipeline': 300 }
10、在 PyCharm 软件左下角单击“Terminal”标签,进入命令行界面,在其中执行 “scrapy crawl bei_bus”命令,启动爬虫项目,查看数据库
程序完整源代码
bei_bus.py:
import scrapy from scrapy import Spider, Request, FormRequest from urllib.parse import urljoin from ..items import BeijingbusItem class BeiBusSpider(scrapy.Spider): name = 'bei_bus' allowed_domains = ['beijing.8684.cn'] start_urls = 'http://beijing.8684.cn/' def start_requests(self): for page in range(1): url = '{url}/list{page}'.format(url=self.start_urls, page=(page + 1)) yield FormRequest(url, callback=self.parse_index) def parse_index(self, reponse): beijing = reponse.xpath('//div[@class="list clearfix"]/a//@href').extract() for c in beijing: urls = urljoin(self.start_urls, c) yield Request(urls, callback=self.parse_detail) def parse_detail(self, response): a = response.xpath('//h1[@class="title"]/text()').extract_first() b = response.xpath('//a[@class="category"]/text()').extract_first() c = response.xpath('//ul[@class="bus-desc"]/li[1]/text()').extract_first() # 格式化数据 ab = BeijingbusItem() for field in ab.fields: ab[field] = eval(field) yield ab def parse(self, response): pass
注:当添加其他字段的爬取时也要进行格式化数据,即在items.py中进行格式化,如下
items.py:
import scrapy #格式化数据 class BeijingbusItem(scrapy.Item): a = scrapy.Field() b = scrapy.Field() c = scrapy.Field()
pipelines.py:
import pymysql from itemadapter import ItemAdapter from beijingbus import settings class MysqlPipeline(object): def __init__(self): self.host = settings.DB_HOST self.user = settings.DB_USER self.pwd = settings.DB_PWD self.db = settings.DB self.charset = settings.DB_CHARSET self.connect() def connect(self): self.conn = pymysql.connect(host=self.host, user=self.user, password=self.pwd, db=self.db, charset=self.charset) self.cursor = self.conn.cursor() def process_item(self, item, spider): sql = 'INSERT INTO businfo (a,b,c)VALUES("%s","%s","%s")' % (item['a'], item['b'], item['c']) self.cursor.execute(sql) self.conn.commit() return item def close_spider(self, spider): self.conn.close() self.cursor.close()
settings.py:
BOT_NAME = 'beijingbus' SPIDER_MODULES = ['beijingbus.spiders'] NEWSPIDER_MODULE = 'beijingbus.spiders' ROBOTSTXT_OBEY = False DEFAULT_REQUEST_HEADERS = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36', } ITEM_PIPELINES = { 'beijingbus.pipelines.MysqlPipeline': 300 } DB_HOST = 'localhost' DB_USER = 'root' DB_PWD = 'dang' DB_CHARSET = 'UTF8' DB = 'studb'
程序框架主体逻辑:
1、修改settings.py将ROBOTSTXT_OBEY的参数改为False
2、修改settings.py添加User-Agent属性
3、编写bei_bus.py
4、编写items.py以格式化数据
5、新建数据库表
6、编写MysqlPipeline.py
7、运行bei_bus爬虫项目
使用Scrapy爬取北京公交信息完成