爬虫学习之scrapy
*
– 前言
– scrapy框架
– scrapy+selenium自动化
前言
此文用于学习SCRAPY
scrapy框架
scrapy是一个用于爬取数据,并对数据进行处理的爬虫框架,使用编写几个模块就可以实现爬虫,并对数据可以做一些想定的处理
scrapy架构图
关于scrapy的组件介绍和流程步骤可以参考博客
https://www.cnblogs.com/wcwnina/p/10399810.html
使用scraoy
创建项目:scrapy startproject proname
进入项目:cd proname
创建爬虫:scrapy genspider spiname(爬虫名) xxx.com (爬取域)
我们简单的爬取dangdang网站的图书信息
在生成的Spiders(testdang)中编写爬虫代码
生成中的start_urls就是爬取的网址填写好后,去分析网站可以很轻松点分析出数据,我们将它解析出来
当数据出来后,问题来了,我们该用什么样的格式方式去将数据接收下来
这里就可以用到Item,将它看成一个可以自己定义的容器去获取数据
代码部分.
spider部分
import scrapy
from studydang.items import StudydangItem
class TestdangSpider(scrapy.Spider):
name = 'testdang'
allowed_domains = ['dangdang.com']
start_urls = ['http://search.dangdang.com/?key=PYTHON&act=input&page_index=1']
def parse(self, response):
print('*' * 70)
dlist = response.selector.css("ul.bigimg li")
for i in dlist:
print('=' * 70)
item = StudydangItem()
item['pic'] = (i.css("a.pic img::attr(src)").extract_first())
if item['pic'] == None:
item['pic'] = (i.css("a.pic img::attr(data-original)").extract_first())
item['name'] = (i.css("p.name a::attr(title)").extract_first())
item['author'] = (i.css("p.search_book_author a::attr(title)").extract_first())
item['price'] = (i.css("p.price span.search_now_price::text").extract_first())
item['time'] = (i.re_first(" /(.*?)"))
yield item
items部分
Define here the models for your scraped items
#
See documentation in:
https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class StudydangItem(scrapy.Item):
# define the fields for your item here like:
pic = scrapy.Field()
name = scrapy.Field()
author = scrapy.Field()
price = scrapy.Field()
time = scrapy.Field()
接下来就是框架的另一个好处,对数据做持久化
我们这里就将数据放进MYSQL数据库中
简单的存储数据库就是连接数据库,执行SQL,关闭数据库连接
首先将连接数据库所用的user,password写入gettings中(这样可以统一,不至于反复写导致写错的问题)然后将gettings中的ITEM_PIPELINES打开,注意数字越小,越先执行。
然后对pipelines进行编辑
代码部分.
import pymysql
使用twsited异步IO框架,实现数据的异步写入。
from twisted.enterprise import adbapi
from studydang import settings
class StudydangPipeline():
def __init__(self):
#连接数据库,使用的参数是在gettings里准备好的
MYSQL_HOST = settings.MYSQL_HOST
MYSQL_DB = settings.MYSQL_DB
MYSQL_USER = settings.MYSQL_USER
MYSQL_PASSWD = settings.MYSQL_PASSWD
MYSQL_PORT = settings.MYSQL_PORT
MYSQL_CHARSET = settings.MYSQL_CHARSET
self.db = pymysql.connect(host=MYSQL_HOST, db=MYSQL_DB, user=MYSQL_USER, password=MYSQL_PASSWD,
port=MYSQL_PORT,
charset=MYSQL_CHARSET)
#建立游标
self.cursor = self.db.cursor()
def process_item(self, item, spider):
#执行SQL语句,将爬取下来的数据储存进数据库
self.cursor.execute("insert into test(pic,name,author,price,time) value (%s,%s,%s,%s,%s)",
(item['pic'], item['name'], item['author'], item['price'], item['time']))
#提交
self.db.commit()
def close_sql(self):
#关闭游标和数据库
self.cursor.close()
self.db.close()
接下来
运行爬虫:scrapy crawl spiname -o file.json
即可
而中间会发现我的框架格式有一点不同 会有一个init.py的文件
这里是为了DEBUG模式,在SCRAPY框架下运行DEBUG模式可以再scrapy.cfg同级目录下创建py文件DEBUG以下代码即可
from scrapy.cmdline import execute
import os
import sys
if __name__ == '__main__':
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
execute(['scrapy','crawl','testdang'])
scrapy+selenium自动化
当一些网站的数据是使用加载的方式呈现,就需要使用selenium自动化打开网站来获取数据。
scrapy使用selenium主要是用download中间件实现,在download中将selenium加入打开网页获取数据返回网站加载好的响应
直接上手,自动点击图片网的下一页持续获取数据。
spider将url给调度器发送,启动download前时,我们需要将中间件打开重写,使用selenium打开网站,并获取网站数据。
selenium的使用这里不多做介绍,将driver加入并打开爬取网站.
middlewares中downloadMiddleware部分
Define here the models for your spider middleware
#
See documentation in:
https://docs.scrapy.org/en/latest/topics/spider-middleware.html
import chardet
from scrapy import signals
from selenium import webdriver
from scrapy.http import HtmlResponse
useful for handling different item types with a single interface
from itemadapter import is_item, ItemAdapter
class SeleniumMiddleware:
@classmethod
def from_crawler(cls, crawler):
# This method is used by Scrapy to create your spiders.
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
crawler.signals.connect(s.spider_close, signal=signals.spider_closed)
return s
def spider_opened(self, spider):
#selenium.webdriver
self.chrome = webdriver.Chrome(
executable_path='xxxxxxxxxxxxxxxxxxxxxx')
def spider_close(self,spider):
#self.chrome.close()
pass
def process_response(self,request,response,spider):
#如果是第一次打开网站第一页,就执行当前网页的获取
if not request.meta.get("nextPage",False):
self.chrome.get(request.url)
webhtml = self.chrome.page_source
#不然就点击下一页,再获取当前网页的数据
else:
self.chrome.find_element_by_link_text("下一页").click()
webhtml = self.chrome.page_source
#将获取的网页数据封装进HtmlResponse.body中
response = HtmlResponse(url=request.url, body=webhtml,encoding="utf-8")
return response
spider部分
import scrapy
from lxml import etree
from studydang.items import StudydangItem
class TestdangSpider(scrapy.Spider):
name = 'pic'
allowed_domains = ['netbian.com']
start_urls = ['https://pic.netbian.com/4kmeinv/']
#爬取页数的判定
p = 2
def parse(self, response):
html = response.body.decode(encoding="utf-8")
xpathBody = etree.HTML(html)
listLie = xpathBody.xpath('//div[@class="slist"]/ul/li')
number = 0
for i in listLie:
item = StudydangItem()
item['name'] = str(i.xpath('./a/@href')[0])
if number < 20:
number = number+1
yield item
else:
if self.p < 3:
self.p = self.p + 1
yield scrapy.Request(url=response.url,meta={"nextPage":True},callback=self.parse, dont_filter=True)
解析部分也不多说了,之前的博客中有对图片网的解析
判断也只是为了限制爬虫的页数,非常简单的逻辑
这边注意的是scrapy.Request中的meta是为了传参进中间件中给与是否执行点击下一页的判断参数
其中item是写好的,如之前一样是为了存进数据库,就不写出来了。
Original: https://blog.csdn.net/weixin_42750816/article/details/117419680
Author: 胡萝卜粥
Title: 爬虫学习之scrapy
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/792112/
转载文章受原作者版权保护。转载请注明原作者出处!