scrapy分页抓取网页( Scrapy二.准备环境三.使用框架1.创建项目使用命令)
优采云 发布时间: 2022-02-05 07:22scrapy分页抓取网页(
Scrapy二.准备环境三.使用框架1.创建项目使用命令)
Python爬虫学习的scrapy框架(一)爬取豆瓣书单
文章目录
Python爬虫学习的scrapy框架(一)爬取豆瓣书单
资源链接
一.什么是 Scrapy
二.准备环境
三.一般流程
四.使用框架
1.创建项目
2.各部分介绍
3.创建爬虫
4.设置数据存储模板
5.分析网页,编写爬虫
6.数据处理
7.设置部分
8.执行爬虫
一.什么是 Scrapy
Scrapy 是一个应用程序框架,用于抓取 网站 数据并提取结构化数据。它可以用于一系列程序,包括数据挖掘、信息处理或存储历史数据。自己写一个Python爬虫也不是不行,但是有框架可以用,何乐而不为呢?相信Scrapy可以事半功倍。与 request 相比,scrapy 侧重于爬虫框架,而不是页面下载。
二.准备环境
scrapy爬虫pypiwin32、lxml、twisted、scrapy、Microsoft Visual C++ 14.0或以上编译环境所需的库
数据库连接模块,pymysql,我用pip安装了上面的库,这里放了清华大学的镜像源 -i /simple
三.一般流程
首先,引擎从调度程序中获取一个链接(URL)用于后续爬取
1.引擎将URL封装成请求(Request)传给下载器,下载器下载资源并封装成响应包(Response)
2.然后,爬虫解析Response。
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 douban命令进入项目所在文件夹
PS D:\pythonpractice> cd douban
PS D:\pythonpractice\douban>
2.各部分介绍
在项目文件夹中,可以看到还有一个与项目同名的文件夹,里面收录了一些文件,
1.items.py 负责建立数据模型,为结构化数据设置数据存储模板,如:Django的Model
2.middlewares.py 是你自己定义的中间件
3.pipelines.py 负责处理spider返回的数据,比如数据持久化
4.settings.py 负责整个爬虫的配置
5.spiders目录负责存放从scrapy继承而来的爬虫类
6.scrapy.cfg 是scrapy的基本配置
3.创建爬虫
使用 scrapy genspider [options] 创建自己的爬虫,
我进入scrapy genspider book,即创建一个叫book的爬虫,domain部分就是爬虫的范围,爬取的网页不能超过这个域名。
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.分析网页,编写爬虫
打开网址链接:豆瓣阅读Top 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,爬虫开始执行