scrapy分页抓取网页( 什么是Scrapy二.准备环境三.大体设置数据存储模板)
优采云 发布时间: 2021-12-24 22:21scrapy分页抓取网页(
什么是Scrapy二.准备环境三.大体设置数据存储模板)
Python爬虫学习的scrapy框架(一)爬取豆瓣书单
文章内容
html
Python爬虫学习的scrapy框架(一)爬取豆瓣书单
资源连接
一.什么是Scrapy
二.准备环境
三.一般流程
四.使用框架python
1.创建项目mysql
2.各部分正则表达式介绍
3.创建爬虫sql
4.设置数据存储模板数据库
5.分析网页,编写爬虫应用
6.数据处理框架
7.设置dom的一部分
8.执行scrapy
一.什么是Scrapy
Scrapy 是一个应用框架,用于抓取 网站 数据并提取结构化数据。它可用于包括数据挖掘、信息处理或存储历史数据在内的一系列程序中。写Python爬虫程序也不是不行,但是有框架可以用,何乐而不为呢?我相信Scrapy可以事半功倍。与请求相比,scrapy 更侧重于爬虫框架而不是页面下载。
二.准备环境
Scrapy爬虫需要库pypiwin32、lxml、twisted、scrapy、Microsoft Visual C++ 14.0以上编译环境
数据库链接模块pymysql,以上库我都是用pip安装的,我把清华大学的镜像源放在这里/simple
三.一般流程
首先,引擎从调度程序获取连接(URL)以进行下一次抓取
1. 引擎将URL封装成请求(Request)发送给下载器,下载器下载资源并封装成响应包(Response)
2. 然后,爬虫解析响应。
3.如果实体(Item)被解析,就会交给实体管道做进一步处理。
4.如果解析出来的是连接(URL),那么这个URL就会交给Scheduler等待爬取。
四.使用框架1.创建项目
使用命令scrapy startproject projectname
PS D:\pythonpractice> scrapy startproject douban
New Scrapy project 'douban', using template directory 'D:\python38install\Lib\site-packages\scrapy\templates\project', created in:
D:\pythonpractice\douban
You can start your first spider with:
cd douban
scrapy genspider example example.com
我用的是vscode,我用ctrl和·调用终端,输入命令,我要去爬豆瓣的一些页面,所以我把它命名为豆瓣,可以看到在你打开的文件夹下出现了一个新文件夹。名字是我做的
以后用cd豆瓣命令进入项目所在的文件夹
PS D:\pythonpractice> cd douban
PS D:\pythonpractice\douban>
2.各部分介绍
在项目文件夹中,可以看到还有一个和项目同名的文件夹,里面有一些文件,
1.items.py 负责创建数据模型,为结构化数据设置数据存储模板,如:Django Model
2.middlewares.py 是自己定义的中间件
3.pipelines.py 负责处理蜘蛛返回的数据,比如数据持久化
4.settings.py 负责整个爬虫的配置
5. spiders目录负责存放从scrapy继承而来的爬虫
6.scrapy.cfg 是scrapy的基本配置
3.构建爬虫
使用scrapy genspider [options] 构建自己的爬虫,
我输入了scrapy genspider来创建一个名为book的爬虫。域名部分是爬虫的范围,被爬取的网页不能超过这个域名。
4.设置数据存储模板
修改以下item.py
import scrapy
class DoubanItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field()
img_src = scrapy.Field()
score = scrapy.Field()
publish_house = scrapy.Field()
publish_detail = scrapy.Field()
slogan = scrapy.Field()
detail_addr = scrapy.Field()
comment_people = scrapy.Field()
5.分析网页,编写爬虫
打开网站链接:豆瓣阅读250强(/top250)
F12打开网页源代码,
能看结构就很清楚了,我需要的是这本书的资料,下面写book.py,
class BookSpider(scrapy.Spider):
name = 'book'
allowed_domains = ['douban.com']
start_urls = ['https://book.douban.com/top250?start=0']
url_sets = set()
def parse(self, response):
if response.url.startswith('https://book.douban.com'):
seclectors = response.xpath('//div[@class="indent"]/table')
for seclector in seclectors:
item = DoubanItem()
item['title'] = seclector.xpath("./tr/td[2]/div/a/@title").extract()[0]
item['img_src'] = seclector.xpath("./tr/td[1]/a/img/@src").extract()[0]
item['publish_detail'] = seclector.xpath("./tr/td[2]/p[@class='pl']/text()").extract()[0]
item['score'] = seclector.xpath("./tr/td[2]/div[@class='star clearfix']/span[@class='rating_nums']/text()").extract()[0]
item['detail_addr'] = seclector.xpath("./tr/td[2]/div[@class='pl2']/a/@href").extract()[0]
#标语爬取
item['slogan'] = seclector.xpath("./tr/td[2]/p[@class='quote']/span/text()").get()
if item['slogan']:
pass
else:
item['slogan'] = '暂无信息'
#评论人数爬取
item['comment_people'] = seclector.xpath("./tr/td[2]/div[@class='star clearfix']/span[@class='pl']/text()").extract()[0]
comment = str(item['comment_people'])
rex = '[0-9]+'
num = re.findall(rex, comment)
if num:
item['comment_people'] = num[0]
else:
item['comment_people'] = '暂无信息'
#出版社爬取
t = str(item['publish_detail'])
s = t.encode() #进行字符串转义
temp = s.decode('utf-8')
pattern="[\u4e00-\u9fa5]*\u51fa\u7248[\u4e00-\u9fa5]*|[\u4e00-\u9fa5]*\u4E66\u5E97[\u4e00-\u9fa5]*" #中文 unicode编码出版 正则表达式
results = re.findall(pattern, temp) #匹配
if results:
item['publish_house'] = results[0]
else:
item['publish_house'] = '暂无信息'
yield item
#分页处理
urls = response.xpath("//div[@class='paginator']/span[@class='next']/a/@href").extract()
for url in urls:
if url.startswith('https://book.douban.com'):
if url in self.url_sets:
pass
else:
self.url_sets.add(url)
yield self.make_requests_from_url(url)
else:
pass
(1) 其中start_urls为起始页,后续页面从网页的pager中获取,但是如果网站使用js进行分页,则没有办法。
(2) 提取网页内容的方法有很多,比如beautifulsoup和lxml,但是scrapy中默认使用selector。相对来说,最好用xpath来分析页面。你可以找来了解一下xpath 自己动手吧,单纯为爬虫做网页分析感觉不难。
(3)书的封面图片,获取地址后,可以选择保存在本地,但是因为我觉得不喜欢把图片上传到我PC上的mysql,总觉得那个不是很靠谱,就爬取它的地址,如果你写了网站,想使用这些图片,应该可以直接使用地址。
(4)出版商信息爬取部分,因为这是作者/出版商/日期/价格组成,我用正则表达式将收录“出版商”、“书店”等关键字的字符串提取出来,方便数据持久化后的数据分析。
6.数据处理
编写以下pipline.py
from itemadapter import ItemAdapter
import urllib.request
import os
import pymysql
class DoubanPipeline:
def process_item(self, item, spider):
#保存图片
# url = item['img_addr']
# req = urllib.request.Request(url)
# with urllib.request.urlopen(req) as pic:
# data = pic.read()
# file_name = os.path.join(r'D:\bookpic',item['name'] + '.jpg')
# with open(file_name, 'wb') as fp:
# fp.write(data)
#保存到数据库
info = [item['title'], item['score'], item['publish_detail'], item['slogan'], item['publish_house'], item['img_src'], item['detail_addr'], item['comment_people']]
connection = pymysql.connect(host='localhost', user='root', password='', database='', charset='utf8')
try:
with connection.cursor() as cursor:
sql = 'insert into app_book (title, score, publish_detail, slogan, publish_house, img_src, detail_addr, comment_people) values (%s, %s, %s, %s, %s, %s, %s, %s)'
affectedcount = cursor.execute(sql, info)
print('成功修改{0}条数据'.format(affectedcount))
connection.commit()
except pymysql.DatabaseError:
connection.rollback()
finally:
connection.close()
return item
7.设置部分
settings.py 增长以下内容
(1)设置处理返回数据的类和执行优先级
ITEM_PIPELINES = {
'douban.pipelines.DoubanPipeline': 100,
}
(2)添加用户代理
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 6.1; WOW64; rv:52.0) G ecko/20100101 Firefox/52.0'
}
8.执行爬虫
输入命令scrapy crawl book,爬虫开始执行