cmd 或 powershell 或 bash 创建爬虫命令:
cmd打开方式:win + R ,输入cmd,回车。
powershell:win + S,输入powershell,回车。
bash:Linux下,ctrl + alt + T。
scrapy startproject 爬虫名称
以爬取Scrapy百度百科为例。
首先在setting中关闭网页爬虫检查:
ROBOTSTXT_OBEY = False
然后在spiders目录下创建Spider01文件:
# Spider01.py
import scrapy
# Spider01类继承自scrapy.Spider类
class Spider01(scrapy.Spider):
# 爬虫名称
name = 'spider01'
# 要爬的网址,是一个列表,可以写多个
start_urls = ['https://baike.baidu.com/item/scrapy/7914913?fr=aladdin']
def parse(self, response):
# 输出网页的html
print(response.text)
再创建文件启动程序RUN.py
# RUN.py
import scrapy.cmdline as cmdline
def run_spider(spider_name: str):
cmdline.execute(("scrapy crawl " + spider_name).split())
if __name__ == '__main__':
run_spider('spider01')
文件目录如图所示
此时运行RUN.py,若在控制台能正确输出网页的html,则说明到此为止是成功的。
使用xpath或者css选择器,选择器的语法在此不赘述。此处只介绍scrapy的API。
import scrapy
class Spider01(scrapy.Spider):
name = 'spider01'
start_urls = ['https://baike.baidu.com/item/scrapy/7914913?fr=aladdin']
def parse(self, response):
# 抽取html中全部的子标题,getall()方法将子标题以列表的形式返回
print(response.xpath('//h2[@class="title-text"]/text()').getall())
# 如果使用get()取代getall(),则只返回html中第一个与之匹配的内容
print(response.xpath('//h2[@class="title-text"]/text()').getall())
items用于格式化存储爬取的数据
首先在item中构造类ScrapydemoItem。
# itmes.py
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class ScrapydemoItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
其次,在spider的parse中调用它,在调用之前,需要导入该类。
import scrapy
from ScrapyDemo.items import ScrapydemoItem
class Spider01(scrapy.Spider):
name = 'spider01'
start_urls = ['https://baike.baidu.com/item/scrapy/7914913?fr=aladdin']
def parse(self, response):
item = ScrapydemoItem()
item['title'] = response.xpath('//h2[@class="title-text"]/text()').get()
item['content'] = response.xpath('//h2[@class="title-text"]/../following-sibling::*[1]/text()').get()
print(item['title'])
print(item['content'])
middleware位于request与response之间,用于更换代理IP、更换Cookies、更换User-Agent、自动重试。
from scrapy import signals
import random
from scrapy.utils.project import get_project_settings
class ScrapydemoDownloaderMiddleware(object):
# 其他方法保持默认即可
def process_request(self, request, spider):
# 发送每个请求时,都会经过该方法
# 因此,该方法适合放置代理IP
proxy = random.choice(get_project_settings()['PROXIES'])
request.meta['proxy'] = proxy
# 使用了settings.py配置文件,因此需要导入它 from scrapy.utils.project import get_project_settings
# 在settings.py中添加代理IP
# PROXIES = ['https://114.217.243.25:8118',
# 'https://125.37.175.233:8118',
# 'http://1.85.116.218:8118']
# 需要看清楚是HTTP型还是HTTPS型的代理IP
return None
写完后,需要去setting.py中找到下面一段代码,并取消注释,即可成功激活。所有中间件都需要激活,不再赘述。
# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
# 'ScrapyDemo.middlewares.ScrapydemoDownloaderMiddleware': 543,
#}
from scrapy import signals
import random
from scrapy.utils.project import get_project_settings
class ScrapydemoDownloaderMiddleware(object):
def process_request(self, request, spider):
ua = random.choice(get_project_settings()['USER_AGENT_LIST'])
request.headers['User-Agent'] = ua
return None
在settings.py中添加请求头
# setting.py
RETRY_ENABLED = True
RETRY_TIMES = 10
RETRY_HTTP_CODES = [
412
]
管道组件,由三个核心方法构成:open_spider、process_item、close_spider。
当爬虫启动时,会触发open_spider组件,此时通常是获取数据库连接,或者打开文件。
当爬虫每yield一个item时,都会经过process_item函数,在这个函数中,我们通常会检查新来的item是否与已有的item重复了。或者将item写入数据库。
当爬虫关闭时,会经过close_spider函数,此时通常是关闭数据库或者文件。
Pipeline组件可以有多个,相当于管道的串联,每个Pipeline都需要在settings.py中开放。
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'scrapyDemo.pipelines.ScrapydemoPipeline': 300, # 300代表优先级,数字越小越先执行
}
下面是一个删除重复item的Pipeline
class ScrapydemoPipeline(object):
# 爬虫启动时执行
def open_spider(self, spider):
self.contentSet = set()
print("hello")
# 每yield一个item时都会经过这个函数
def process_item(self, item, spider):
if item["content"] not in self.contentSet:
self.contentSet.add(item["content"])
# 在这里可以将item写入文件或数据库
# Pipeline组件可以有多个,在settings.py文件中设置优先级
return item
else:
# item重复了
pass
# 爬虫结束时执行
def close_spider(self, spider):
print("bye")