004 使用scrapy框架爬虫

0. 建立housePro的scrapy爬虫框架

# 1. 在终端输入,建立housePro项目
scrapy startproject housePro
# 2. 进入housePro
cd housePro
# 3. 建立爬虫文件
scrapy genspider house www.xxx.com
# 4. 执行程序
scrapy crawl house

1.  用scrapy爬取网站信息

li_list = response.xpath('//div[@class="list_wrap"]/ul')
        for li in li_list:
            li = li.xpath('./li//h1/a/text()').extract()  # 要用extract()函数提取data数据
            print(li)
       li = li.xpath('./li//h1/a/text()').extract_first()

 2. scrapy进行数据解析

 调用parse的response参数,其中response对象可以直接调用xpath方法

3. scrapy的持久化存储

使用管道进行持久化流程

  • 1.获取解析到的数据值
  • 2.将解析到的数据值存储到item对象
  • 3.通过yield关键字提交到管道
  • 4.在管道文件中进行持久化存储的编写(process_item)
  • 5.在配置文件中开启管道
实例化一个item类型的对象的方法
item = BossproItem()
将解析到的数据值存储到item对象中
item['name'] = name
item['salary'] = salary
item['address'] = address
将item对象提交管道进行存储
yield item

对于scrapy的持久化存储,需要用到两个文件,一个是items,另一个是pipelines。

items用来定义存储数据的变量名

pipelines用来进行数据的存储

  open_spider:执行pipelines时,会自动执行

  close_spider:用来关闭数据库连接时使用

  process_item:用来存储参数item中传入的参数

最重要的是要进pipelines从注释中解救出来

ITEM_PIPELINES = {
'BossPro.pipelines.BossproPipeline': 300,
'BossPro.pipelines.MysqlPipeline': 220,
'BossPro.pipelines.RedisPipeline': 200,
}

 

class BossproPipeline(object):

    fp = None
    # 只会被执行一次
    def open_spider(self, spider):
        print('开始爬虫')
        self.fp = open('./Boss.txt', 'w', encoding='utf-8')

    def process_item(self, item, spider):
        # 爬虫文件每提交一次,该方法就会调用一次
        # 注意:默认情况下,管道机制没有开启,需要手动开启
        self.fp.write(item['name'] + '===>' + item['salary'])

        return item

    def close_spider(self, spider):
        print('爬虫结束')
        self.fp.close()
存储成txt类型
class MysqlPipeline(object):

    def open_spider(self, spider):
        self.conn = pymysql.Connect(host='127.0.0.1', user='root', passwd='1111', db='crm')

    def process_item(self, item, spider):
        self.cursor = self.conn.cursor()
        sql = 'insert into Boss (name, salary, address) values ("%s", "%s", "%s")' % (item['name'], item['salary'], item['address'])
        # print(sql)
        try:
            self.cursor.execute(sql)
            self.conn.commit()
        except Exception as e:
            print(e)
            self.conn.rollback()
        self.cursor.close()
        return item

    def close_spider(self, spider):
        self.conn.close()
存储到mysql中
class RedisPipeline(object):

    conn = None

    def open_spider(self, spider):
        self.conn = Redis(host='127.0.0.1', port=6379)
        print(self.conn)

    def process_item(self, item, spider):
        dic = {
            'name': item['name'],
            'salary': item['salary'],
            'address': item['address'],
        }
        self.conn.lpush('Boss', dic)
        return item
存储到redis中

 4. 使用scrapy发送post请求

 # 作用:将起始url列表中的url进行get请求的发送
    def start_requests(self):
        data = {
            'kw': 'dog',
        }
        for url in self.start_urls:

            yield scrapy.FormRequest(url=url, callback=self.parse, formdata=data)
发送Post请求

5. 输出日志等级

LOG_LEVEL = 'ERROR'
LOG_FILE = './log.txt'

 6. 请求传参

在Request中加入meta参数,以字典方式存入

yield scrapy.Request(url=detail_url, callback=self.get_detail, meta={'item': item})
item = response.meta['item'] 

7. 提高效率的几种方法

CONCURRENT_REQUESTS = 10
LOG_LEVEL = 'ERROR'
COOKIES_ENABLED = False
RETRY_ENABLED = False
DOWNLOAD_TIMEOUT = 5

8. 修改代理IP和UA值

  • 修改代理IP

在下载中间键中修改process_request函数

# 拦截请求 request参数就是拦截到的请求
def process_request(self, request, spider):
print('下载中间件' + request.url)
if request.url.split(':')[0] == 'http':
request.meta['proxy'] = 'http://103.42.213.176:8080'
else:
request.meta['proxy'] = 'https://218.60.8.98:3129'

return None

需要在settings中开启下载中间键

DOWNLOADER_MIDDLEWARES = {
'proxyPro.middlewares.ProxyproDownloaderMiddleware': 543,
}
  • 修改UA值
def process_request(self, request, spider):
print('下载中间件' + request.url)
request.headers['User-Agent'] = 'UA值'

return None

9. 使用selenium进行动态数据的获取 

需要在spider中先实例化一个浏览器对象,不能在中间件中实例化

def __init__(self):
# 实例化一个浏览器对象
self.bro = webdriver.Chrome(executable_path='F:\\anaconda\chromedriver.exe')

def close_spider(self, spider):
self.bro.quit()
    def process_response(self, request, response, spider):
        if request.url in ['https://war.163.com/']:
            # 处理相应对象
            bro = spider.bro  # 获取在爬虫文件中创建好的浏览器对象
            bro.get(request.url)
            sleep(1)
            js = 'window.scrollTo(0, document.body.scrollHeight)'
            bro.execute_script(js)
            sleep(0.5)
            bro.execute_script(js)
            sleep(0.5)
            bro.execute_script(js)
            page_text = bro.page_source  # 需要的页面
            # 创建一个新的相应对象并且将上述获取的页面数据加载到响应对象中,
            # 然后将响应对象返回

            return HtmlResponse(url=bro.current_url, body=page_text, encoding='utf-8', request=request)
        return response
中间键中拦截响应进行动态加载

 10. crawlspider

建立crawlSpider实例

  scrapy genspider -t crawl crawlDemo www.xxxx.com

 # 连接提取器:(follow=False)就是用来提取起始url对应页面中符合要求的连接
    link = LinkExtractor(allow=r'/all/hot/recent/\d+')

    rules = (
        # 规则解析器对象:将连接提取器提取的连接对应的页面源码数据根据要求进行解析
        Rule(link, callback='parse_item', follow=False),
    )

 

posted @ 2019-04-15 19:38  安智伟  阅读(176)  评论(0编辑  收藏  举报