做了一个电商的爬虫,仅做学习使用
记录一下遇到的坑:
整个开发步骤为,利用scrapy爬几大电商网站的商品图片,然后开发UI,根据输入的信息,执行不同的爬虫。坑就主要在这个地方
scrapy框架,在settings.py中设置整个项目的配置信息,项目里面所有的spider公用一个配置,不同的爬虫,需要使用不同的配置,即使用不同的settings启动爬虫:
2019年4月23日更新
scrapy框架中,settings有其优先级,官方文档(scrapy-settings)中有如下说明:
设定可以通过多种方式设置,每个方式具有不同的优先级。 下面以优先级降序的方式给出方式列表:
1. 命令行选项(Command line Options)(最高优先级)
2. 每个spider的设定(customer_settings)
3. 项目设定模块(Project settings module)
4. 命令默认设定模块(Default settings per-command)
5. 全局默认设定(Default global settings) (最低优先级)
例:scrapy crawl myspider -s LOG_FILE=log.log -s IMAGES_SCORE=D:/images
与命令行传参类似,通过custom_settings可以在spider中传入自定义的参数来修改settings
class JdSpider(scrapy.Spider):
name = 'jd'
allowed_domains = ['jd.com', 'p.3.cn', 'jd.hk']
def __init__(self, name, images_store, host, port, username, password, db_name, ):
self.keyword = name
# 动态配置settings
self.custom_settings = {
"IMAGES_STORE": images_store,
"MYSQL_HOST": host,
"MYSQL_USER": username,
"MYSQL_PASSWORD": pasword,
"MYSQL_PORT": port,
"MYSQL_DBNAME": db_name,
"MYSQL_CHARSET": 'utf8'
}
super(JdSpider, self).__init__() # 初始化父类放在最后,才能初始化父类的类变量
...
首先要知道如何使用脚本启动爬虫,scrapy提供了两种方式CrawlerProcess和CrawlerRunner,这里以CrawlerProcess为例:
crawl = CrawlerProcess(get_project_settings())
crawl.crawl(myspider)
crawl.start()
get_project_settings()获取的即为全局的设置,所以可以通过创建不同settings,或者修改全局的settings来启动爬虫
# 1. 创建settings
settings = Settings()
settings.set("ITEM_PIPELINES" , {
'pipelines.DuplicatesPipeline': 200,
'pipelines.IpProxyPoolPipeline': 300,
})
settings.set("DEFAULT_REQUEST_HEADERS",{
'Accept': 'text/html, application/xhtml+xml, application/xml',
'Accept-Language': 'zh-CN,zh;q=0.8'}
)
settings.set("DOWNLOADER_MIDDLEWARES",{
'useragent_middlewares.UserAgent': 1,
'proxy_middlewares.ProxyMiddleware':100,
'scrapy.downloadermiddleware.useragent.UserAgentMiddleware' : None,
}
)
settings.set("DOWNLOAD_DELAY",1)
settings.set("COOKIES_ENABLED",False)
settings.set("ROBOTSTXT_OBEY",True)
# 2. 或修改项目settings
settings = get_project_settings()
settings.set('IMAGES_STORE', 'D:/images3')
crawl = CrawlerProcess(settings)
crawl.crawl(myspider)
crawl.start()
scrapy一般用命令启动,在程序中,可以利用cmdline执行对应的命令来启动,可以利用scrapy内置的crawler类来启动(但由于在子线程中启动会有一些bug)。
开启一个子线程执行爬虫,并不断传递信号给主线程,来实时获取信息。但scrapy是一个独立的框架,无法把子线程中定义的信号,放到scrapy模块中去发送。
而scrapy框架自带的信号,也无法传递到scrapy外面?
所以需要使用一些其他的方法,来获取爬虫的运行情况。
一个是将信息写入文件中,从文件中获取,但必须在爬虫结束之后,才获取,另一个方法是开一个进程执行scrapy,并获取进程标准输出。
spider_cmdline = "scrapy crawl {} -a name={} --logfile=log.log".format(self.spider_name, self.keyword)
p = subprocess.Popen(spider_cmdline, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
self.message_singal.emit(' 爬虫已启动')
# 获取返回结果(百分比,和当前下载记录),信号返回两个变量
while True:
if subprocess.Popen.poll(p) is None: # 结束为-1,包含输出为空
data = p.stdout.readline().decode('utf-8').strip()
if data == 'close':
self.message_singal.emit(data) # 发送内容
else:
print("data: ", data)
if data.isdigit():
self.percent_signal.emit(int(data)) # 发送进度信号
else:
# print("爬虫结束")
# 杀死子进程
self.message_singal.emit('爬虫完成,可关闭该窗口,进行其他爬虫任务')
p.terminate()
p.kill()
break
time.sleep(2)
另外:
PYQT5开启多个线程和窗口,多线程与多窗口的交互
PyQt5和Scrapy开发可视化爬虫(二)