实现目标:
1. 通过scrapy框架爬取新浪五个分类主页的数据信息
2. 并实现持久化存储进mysql数据库
主要技术路线:
scrapy,selenium,webdriver,datetime,re,python的orm框架sqlalchemy
一、爬虫框架scrapy
cmd命令行
创建scrapy爬虫项目:scrapy startproject sina sina.com
cd进入 sina文件夹
创建爬虫spider:scrapy genspider sina1
二、编写spider
单个spider的整体结构:
1. __init()初始化函数
2. start_request()调度每一条url
3. parse()通过创建webdriver实例,使用Xpath语法定位元素,操作页面,爬取数据
4. parse_namedetail解析每一个大页面的中爬取出来的每一条子页面中的信息
1. __init()初始化函数:
初始化url_list
初始化page和flag参数
初始化self.options——关于webdriver的一些参数
def __init__(self,page=None,flag=None,*args,**kwargs):
#一些参数初始化
super(Sina1Spider,self).__init__(*args,**kwargs)
self.page = int(page) #爬多少页,代码里写不科学,作为函数参数传进来
self.flag = int(flag) #具体数值在哪里写入呢?在main.py文件的命令里写入
self.start_urls = ['https://news.sina.com.cn/china/',
'https://ent.sina.com.cn/film/',
'https://ent.sina.com.cn/zongyi/',
'https://ent.sina.com.cn/star/',
'http://eladies.sina.com.cn/']
self.option = webdriver.ChromeOptions()
self.option.add_argument('headless') #不打开浏览器
self.option.add_argument('no-sandbox') #不打开沙盒
self.option.add_argument('--blink-setting=imagesEnabled=false') #不要图片
2. start_request
def start_requests(self):
"""
从初始化方法的start_url中解析出单个url
并通过yield关键字产生Request对象,通过callback参数回调给parse方法
"""
for url in self.start_urls:
yield Request(url=url,callback=self.parse)
3. parse函数
关键操作:
- 如何操作窗口向下滑动
driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")
- 所有item都使用PipeLines中创建的DataItem数据类型
item = DataItem()
- 如何通过Xpath语法精准定位title和time元素
title = driver.find_elements_by_xpath("//h2[@class='undefined']/a[@target='_blank']")
- 新闻的时间信息不相同,如何通过预处理将其转换为统一格式
eachtime = eachtime.replace('今天',str(today.month)+'月'+str(today.day)+'日')
- 如何比较新闻发生的时间和today,yesterday?
yesterday = (datetime.datetime.now() + datetime.timedelta(days=-1)).strftime("%Y-%m-%d")
- 如何将爬取的数据进一步解析?
通过yield一个Request对象,其中有一个参数callback,该参数指定了Request对象该传给哪一个函数,与此同时也将href和item信息以参数形式穿进去yield Request(response.urljoin(href),meta={'name':item},callback=self.parse_namedetail)
def parse(self, response):
"""
解析内容
:param response:
:return:
"""
driver = webdriver.Chrome(chrome_options=self.option)
driver.set_page_load_timeout(30