Scrapy框架入门-xpath

如果对xpath语法比较了解,可以只阅读总结部分

scrapy简介
异步和非阻塞的区别
异步和非阻塞的区别
scrapy爬虫的流程
流程
各模块的作用
模块的作用
入门
创建项目
scrapy startproject myspider

myspider是项目名

生成一个爬虫
scrapy genspider itcast "itcast.cn"

参数含义:itcast是爬虫名字,itcast.cn是爬取的范围,一般是域名
执行命令后,会在myspider/spiders生成itcast.py文件
myspider/spiders/itcast.py

import scrapy
class ItcastSpider(scrapy.Spider):
    name = 'itcast'
    # 允许爬取范围
    allowed_domains = ['itcast.cn']
    # 最开始请求url地址
    start_urls = ['http://itcast.cn/']

    def parse(self, response):
        pass
提取数据

完善spider,使用xpath等办法

保存数据

pipeline中保存数据

启动爬虫
cd 项目根目录
scrapy crawl 爬虫名字
目录结构
|____myspider
| |____spiders
| | |______init__.py
| | |______pycache__
| | | |______init__.cpython-37.pyc
| | |____itcast.py
| |______init__.py
| |______pycache__
| | |____settings.cpython-37.pyc
| | |______init__.cpython-37.pyc
| |____middlewares.py
| |____settings.py
| |____items.py
| |____pipelines.py
|____scrapy.cfg

scrapy.cfg

[settings]
# 项目配置文件settings.py
default = myspider.settings

[deploy]
# 代码发布
#url = http://localhost:6800/
project = myspider

settings.py

  1. 设置日志级别
# 日志等级
LOG_LEVEL = "WARNING"

LOG_LEVEL = "WARNING"表示warning以下的错误不打印日志

xpath语法
基本语法
  1. 选取节点
路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点。
/bookstore 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素
//book 选取所有 book 子元素,而不管它们在文档中的位置
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置
//@lang 选取名为 lang 的所有属性,获得lang属性的值
  1. 谓语(Predicates)
    查找某个特定的节点或者包含某个指定的值的节点。谓语嵌在方括号中
路径表达式 结果
. 当前元素
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素
/bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素
//title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00
/bookstore/book[price>35.00]//title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00
./book/following-sibling::price[1] 获取book节点的第一个price兄弟节点

注意:以下使用场景

test

如果是用

xpath('//div[@class="a"]')

会取不到里面的值,可以用如下的表达式:

xpath('//div[contains(@class,"a")]')   #它会取得所有class包含a的元素

同时包含多个类的情况

xpath('//div[contains(@class,"a") and contains(@class,"b")]') #它会取class同时有a和b的元素

不要在任何选择器中出现tbody标签,可以阅读这篇文章https://hexfox.com/p/having-trouble-extracting-the-tbody-element-during-my-web-scrape/,了解为什么

Xpath选择器://table[@class="some_class"]/tbody/tr=> //table[@class="some_class"]/tr。

CSS选择器:table.some_class>tbody>tr=> table.some_class>tr

//这类只能在第一次选择时使用,以/开头表示从任意目录开始找

  1. 取值
表达式 示例 结果
text() /bookstore/book[1]/text() 选取属于 bookstore 子元素的第一个 book 元素,提取其文本
text() //bookstore/a[text()='abc'] 选取bookstrore子元素中文本为abc的a标签
extract() response.xpath("//div[@class='tea_con']//h3/text()").extract() 返回一个标签列表,不加extract()返回的是选择器
extract_first() item['title'] = li.xpath(".//h4/text()").extract_first() 返回一个标签,不加extract_first()返回的是选择器
@src //img/@src 返回所有图片的src
语法示例
  1. 路径选择 //
//div[@class='tea_con']//li

选取带有class属性,且值为tea_con的所有div元素下的所有li元素

  1. extract()
def parse(self, response):
    ret1 = response.xpath("//div[@class='tea_con']//h3/text()").extract()
    print(ret1)

extract()返回一个列表,里面是提取的元素

  1. extract_first()
def parse(self, response):
    li_list = response.xpath("//div[@class='tea_con']//li")
    for li in li_list:
        item = {}
        item['name'] = li.xpath(".//h3/text()").extract()[0]
        item['title'] = li.xpath(".//h4/text()").extract()[0]
        #item['title'] = li.xpath(".//h4/text()").extract_first()
        print(item)

extract()[0]表示选择符合条件的第一个元素,该方法如果数组为空会报错,而extract_first()在数组为空时会返回None,不会报错
使用场景
当只需要列表项中的数据的第一个结果时用extract_first()

完整案例
  1. 提取数据
    itcast.py
class ItcastSpider(scrapy.Spider):
    name = 'itcast'
    # 允许爬取范围
    allowed_domains = ['itcast.cn']
    # 最开始请求url地址
    start_urls = ['http://www.itcast.cn/channel/teacher.shtml']

# //表示从匹配的当前节点

    def parse(self, response):

        # ret1 = response.xpath("//div[@class='tea_con']//h3/text()").extract()
        # print(ret1)
        # scrapy返回的不是普通的列表,可以使用extract()提取列表中每项元素
        li_list = response.xpath("//div[@class='tea_con']//li")
        for li in li_list:
            item = {}
            item['name'] = li.xpath(".//h3/text()").extract_first()
            item['title'] = li.xpath(".//h4/text()").extract_first()
            yield item

最后yeild将提取的每一项交给pipiline处理

  1. 开启pipeline
    settings.py
ITEM_PIPELINES = {
   'myspider.pipelines.MyspiderPipeline': 300,
}

myspider.pipelines.MyspiderPipeline表示项目名.文件名.类名
300是优先级,数字越小,优先级越高

注意:

  1. 只有开启pipeline,才能在(pipelines.py)中对数据进行处理
  2. 优先级较高的pipeline必须把数据return回去,否则后面的pipeline不能接收到数据
总结
完善spider
parse

pipeline

你可能感兴趣的:(Scrapy框架入门-xpath)