前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Scrapy 入门教程

Scrapy 入门教程

作者头像
Stanley Sun
发布于 2019-09-23 07:00:57
发布于 2019-09-23 07:00:57
84000
代码可运行
举报
运行总次数:0
代码可运行

创建一个Scrapy项目

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
scrapy startproject tutorial

运行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(scrapy) localhost:scrapy stanley$ scrapy startproject tutorial
New Scrapy project 'tutorial', using template directory '/Users/stanley/virtualenv/scrapy/lib/python2.7/site-packages/scrapy/templates/project', created in:
    /Users/stanley/virtualenv/scrapy/tutorial

You can start your first spider with:
    cd tutorial
    scrapy genspider example example.com

目录结构

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
|____scrapy.cfg   #部署配置文件
|____tutorial     #项目的python模块
| |______init__.py
| |____items.py        #item文件
| |____middlewares.py  #middlewares文件
| |____pipelines.py    #pipeline文件
| |____settings.py     #项目配置
| |____spiders         #存放爬虫的目录
| | |______init__.py

第一个爬虫

爬虫就是Scrapy用来从网站抓取数据的类,它们都继承于scrapy.Spider类。

编写第一个爬虫类,文件名为quotes_spider.py,放在tutorial/spiders下面。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import scrapy


class QuotesSpider(scrapy.Spider):
    name = "quotes"

    def start_requests(self):
        urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        page = response.url.split("/")[-2]
        filename = 'quotes-%s.html' % page
        with open(filename, 'wb') as f:
            f.write(response.body)
        self.log('Saved file %s' % filename)
  • name: 这个爬虫的名字
  • start_requests(): 返回一个可迭代的Rquest,爬虫会从这些Request开始请求数据。可迭代的Request可以是一个list,也可以是一个generator函数。Generator函数可参见 https://cloud.tencent.com/developer/article/1510692
  • parse():用来解析爬虫读取的数据。

让爬虫跑起来

到项目到顶级目录,然后执行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
scrapy crawl quotes

这个命令会运行名字为quotes的爬虫,也就是上面写的那个。

注意:这里的参数是crawl,不是runspider。

运行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...

2017-08-08 07:17:01 [scrapy.core.engine] INFO: Spider opened
2017-08-08 07:17:01 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2017-08-08 07:17:01 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2017-08-08 07:17:03 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://quotes.toscrape.com/robots.txt> (referer: None)
2017-08-08 07:17:03 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/1/> (referer: None)
2017-08-08 07:17:03 [quotes] DEBUG: Saved file quotes-1.html
2017-08-08 07:17:03 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/2/> (referer: None)
2017-08-08 07:17:03 [quotes] DEBUG: Saved file quotes-2.html
2017-08-08 07:17:03 [scrapy.core.engine] INFO: Closing spider (finished)
2017-08-08 07:17:03 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 675,
 'downloader/request_count': 3,
 'downloader/request_method_count/GET': 3,
 'downloader/response_bytes': 5976,
 'downloader/response_count': 3,
 'downloader/response_status_count/200': 2,
 'downloader/response_status_count/404': 1,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2017, 8, 7, 23, 17, 3, 793776),
 'log_count/DEBUG': 6,
 'log_count/INFO': 7,
 'memusage/max': 43855872,
 'memusage/startup': 43855872,
 'response_received_count': 3,
 'scheduler/dequeued': 2,
 'scheduler/dequeued/memory': 2,
 'scheduler/enqueued': 2,
 'scheduler/enqueued/memory': 2,
 'start_time': datetime.datetime(2017, 8, 7, 23, 17, 1, 659265)}
2017-08-08 07:17:03 [scrapy.core.engine] INFO: Spider closed (finished)

目录下还会生成2个文件 quotes-1.htmlquotes-2.html, 它们是爬虫里的parse()函数生成的。

简化start_requests()

start_requests() 生成一系列 scrapy.Request对象,我们也可以start_urls 来代替这个种方式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import scrapy

class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = [
        'http://quotes.toscrape.com/page/1/',
        'http://quotes.toscrape.com/page/2/',
    ]

    def parse(self, response):
        page = response.url.split("/")[-2]
        filename = 'quotes-%s.html' % page
        with open(filename, 'wb') as f:
            f.write(response.body)

解析数据

可以使用命令行来解析运行过程中的数据,比如运行下面的命令,Scrapy数据存储到默认的变量里。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
scrapy shell 'http://quotes.toscrape.com/page/1/'

运行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2017-08-08 11:45:41 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: tutorial)
2017-08-08 11:45:41 [scrapy.utils.log] INFO: Overridden settings: {'NEWSPIDER_MODULE': 'tutorial.spiders', 'ROBOTSTXT_OBEY': True, 'DUPEFILTER_CLASS': 'scrapy.dupefilters.BaseDupeFilter', 'SPIDER_MODULES': ['tutorial.spiders'], 'BOT_NAME': 'tutorial', 'LOGSTATS_INTERVAL': 0}

...

2017-08-08 11:45:41 [scrapy.core.engine] INFO: Spider opened
2017-08-08 11:45:42 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://quotes.toscrape.com/robots.txt> (referer: None)
2017-08-08 11:45:43 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/1/> (referer: None)
[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    <scrapy.crawler.Crawler object at 0x10fc21190>
[s]   item       {}
[s]   request    <GET http://quotes.toscrape.com/page/1/>
[s]   response   <200 http://quotes.toscrape.com/page/1/>
[s]   settings   <scrapy.settings.Settings object at 0x10fc21a90>
[s]   spider     <DefaultSpider 'default' at 0x10feb3650>
[s] Useful shortcuts:
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects 
[s]   shelp()           Shell help (print this help)
[s]   view(response)    View response in a browser
>>> 

request, response,settings等等都是存储数据的变量,可以通过命令行查看和操作它们。如,通过css选择器找到页面中的title标签。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> response.css('title')
[<Selector xpath=u'descendant-or-self::title' data=u'<title>Quotes to Scrape</title>'>]
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> response.css('title::text').extract()
[u'Quotes to Scrape']

如果不用::text则会选择整个元素,包含标签。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> response.css('title').extract()
[u'<title>Quotes to Scrape</title>']

extract()返回的是一个列表,extract_first()返回第一条。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> response.css('title::text').extract_first()
u'Quotes to Scrape'

正则表达式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> response.css('title::text').re(r'Quotes.*')
['Quotes to Scrape']
>>> response.css('title::text').re(r'Q\w+')
['Quotes']
>>> response.css('title::text').re(r'(\w+) to (\w+)')
['Quotes', 'Scrape']

直接打开浏览器观看数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
view(response)

XPath简介

除了CSS选择器,还可以使用XPath表达式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> response.xpath('//title')
[<Selector xpath='//title' data='<title>Quotes to Scrape</title>'>]
>>> response.xpath('//title/text()').extract_first()
'Quotes to Scrape'

提取quote和author

http://quotes.toscrape.com 页面里每一个quote都是一个html元素。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<div class="quote">
    <span class="text">“The world as we have created it is a process of our
    thinking. It cannot be changed without changing our thinking.</span>
    <span>
        by <small class="author">Albert Einstein</small>
        <a href="/author/Albert-Einstein">(about)</a>
    </span>
    <div class="tags">
        Tags:
        <a class="tag" href="/tag/change/page/1/">change</a>
        <a class="tag" href="/tag/deep-thoughts/page/1/">deep-thoughts</a>
        <a class="tag" href="/tag/thinking/page/1/">thinking</a>
        <a class="tag" href="/tag/world/page/1/">world</a>
    </div>
</div>

找到quote

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> response.css("div.quote")
[<Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>, <Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>, <Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>, <Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>, <Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>, <Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>, <Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>, <Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>, <Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>, <Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>]
>>> 

上面是一个数组,说明找到很多quote. 选组第一个

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> response.css("div.quote")[0]
<Selector xpath=u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' quote ')]" data=u'<div class="quote" itemscope itemtype="h'>

提取 title, author 和 tags

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> quote = response.css("div.quote")[0]
>>> title = quote.css("span.text::text").extract_first()
>>> title
u'\u201cThe world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.\u201d'
>>> author = quote.css("small.author::text").extract_first()
>>> author
u'Albert Einstein'
>>> 
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> tags = quote.css("div.tags a.tag::text").extract()
>>> tags
[u'change', u'deep-thoughts', u'thinking', u'world']

遍历

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> for quote in response.css("div.quote"):
...   text = quote.css("span.text::text").extract_first()
...   author = quote.css("small.author::text").extract_first()
...   tags = quote.css("div.tags a.tag::text").extract()
...   print(dict(text=text, author=author, tags=tags))
... 
{'text': u'\u201cThe world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.\u201d', 'tags': [u'change', u'deep-thoughts', u'thinking', u'world'], 'author': u'Albert Einstein'}
{'text': u'\u201cIt is our choices, Harry, that show what we truly are, far more than our abilities.\u201d', 'tags': [u'abilities', u'choices'], 'author': u'J.K. Rowling'}
{'text': u'\u201cThere are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.\u201d', 'tags': [u'inspirational', u'life', u'live', u'miracle', u'miracles'], 'author': u'Albert Einstein'}

...

在爬虫中提取数据

命令行的提取数据方法可以应用到爬虫中,改进我们到爬虫

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import scrapy


class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = [
        'http://quotes.toscrape.com/page/1/',
        'http://quotes.toscrape.com/page/2/',
    ]

    def parse(self, response):
        for quote in response.css('div.quote'):
            yield {
                'text': quote.css('span.text::text').extract_first(),
                'author': quote.css('small.author::text').extract_first(),
                'tags': quote.css('div.tags a.tag::text').extract(),
            }

运行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>>scrapy crawl quotes

...

{'text': u'\u201cThe world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.\u201d', 'tags': [u'change', u'deep-thoughts', u'thinking', u'world'], 'author': u'Albert Einstein'}
2017-08-08 13:00:58 [scrapy.core.scraper] DEBUG: Scraped from <200 http://quotes.toscrape.com/page/1/>
{'text': u'\u201cIt is our choices, Harry, that show what we truly are, far more than our abilities.\u201d', 'tags': [u'abilities', u'choices'], 'author': u'J.K. Rowling'}
...

存储数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
scrapy crawl quotes -o quotes.json

quotes.json

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[
{"text": "\u201cThe world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.\u201d", "author": "Albert Einstein", "tags": ["change", "deep-thoughts", "thinking", "world"]},
{"text": "\u201cIt is our choices, Harry, that show what we truly are, far more than our abilities.\u201d", "author": "J.K. Rowling", "tags": ["abilities", "choices"]},
...

Following links

我们希望通过第一个页面,爬到一个网站到所有页面。这就需要把页面到链接找到,继续爬下去。实例中到网站有一个next page链接,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<ul class="pager">
    <li class="next">
        <a href="/page/2/">Next <span aria-hidden="true">&rarr;</span></a>
    </li>
</ul>

定位到这个元素,并把href解析出来

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> response.css('li.next a::attr(href)').extract_first()
u'/page/2/'

修改代码,递归抓取网页

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import scrapy


class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = [
        'http://quotes.toscrape.com/page/1/',
    ]

    def parse(self, response):
        for quote in response.css('div.quote'):
            yield {
                'text': quote.css('span.text::text').extract_first(),
                'author': quote.css('small.author::text').extract_first(),
                'tags': quote.css('div.tags a.tag::text').extract(),
            }

        next_page = response.css('li.next a::attr(href)').extract_first()
        if next_page is not None:
            next_page = response.urljoin(next_page)
            yield scrapy.Request(next_page, callback=self.parse)

response.urljoin把url会把网址和next_page的相对路径拼成一个绝对地址。它不是直接在response.url后加上next_page,而是在跟路径上加,看下面的测试。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> next_page = response.css('li.next a::attr(href)').extract_first()
>>> next_page
u'/page/2/'
>>> response.url
'http://quotes.toscrape.com/page/1/'
>>> response.urljoin(next_page)
u'http://quotes.toscrape.com/page/2/'

简化scrapy.Request

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
next_page = response.css('li.next a::attr(href)').extract_first()
        if next_page is not None:
            yield response.follow(next_page, callback=self.parse)
...

response.follow不需要拼接url.

response.follow()不仅可以传String, 也可以直接传Selector. 下面的代码循环会对页面所有类似对链接进行递归爬取。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for href in response.css('li.next a::attr(href)'):
    yield response.follow(href, callback=self.parse)

对于<a>元素,response.follow有一个更简洁对办法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for a in response.css('li.next a'):
    yield response.follow(a, callback=self.parse)

另一个例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import scrapy


class AuthorSpider(scrapy.Spider):
    name = 'author'

    start_urls = ['http://quotes.toscrape.com/']

    def parse(self, response):
        # follow links to author pages
        for href in response.css('.author + a::attr(href)'):
            yield response.follow(href, self.parse_author)

        # follow pagination links
        for href in response.css('li.next a::attr(href)'):
            yield response.follow(href, self.parse)

    def parse_author(self, response):
        def extract_with_css(query):
            return response.css(query).extract_first().strip()

        yield {
            'name': extract_with_css('h3.author-title::text'),
            'birthdate': extract_with_css('.author-born-date::text'),
            'bio': extract_with_css('.author-description::text'),
        }

这个爬虫从首页开始,会爬取作者页以及下一页。

运行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
scrapy crawl author -o author.json

结果文件author.json,里面存储了所有author的name,birthdate和bio信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[
{"bio": "Marilyn Monroe (born Norma Jeane Mortenson; June 1, 1926 \u2013 August 5, 1962) was an American actress, model, and singer, who became a major sex symbol, starring in a number of commercially successful motion pictures during the 1950s and early 1960s.After spending much of her childhood in foster homes, Monroe began a career as a model, which led to a film contract in 1946 with Twentieth Century-Fox. Her early film appearances were minor, but her performances in The Asphalt Jungle and All About Eve (both 1950), drew attention. By 1952 she had her first leading role in Don't Bother to Knock and 1953 brought a lead in Niagara, a melodramatic film noir that dwelt on her seductiveness. Her \"dumb blonde\" persona was used to comic effect in subsequent films such as Gentlemen Prefer Blondes (1953), How to Marry a Millionaire (1953) and The Seven Year Itch (1955). Limited by typecasting, Monroe studied at the Actors Studio to broaden her range. Her dramatic performance in Bus Stop (1956) was hailed by critics and garnered a Golden Globe nomination. Her production company, Marilyn Monroe Productions, released The Prince and the Showgirl (1957), for which she received a BAFTA Award nomination and won a David di Donatello award. She received a Golden Globe Award for her performance in Some Like It Hot (1959). Monroe's last completed film was The Misfits, co-starring Clark Gable with screenplay by her then-husband, Arthur Miller.Marilyn was a passionate reader, owning four hundred books at the time of her death, and was often photographed with a book.The final years of Monroe's life were marked by illness, personal problems, and a reputation for unreliability and being difficult to work with. The circumstances of her death, from an overdose of barbiturates, have been the subject of conjecture. Though officially classified as a \"probable suicide\", the possibility of an accidental overdose, as well as of homicide, have not been ruled out. In 1999, Monroe was ranked as the sixth greatest female star of all time by the American Film Institute. In the decades following her death, she has often been cited as both a pop and a cultural icon as well as the quintessential American sex symbol.", "name": "Marilyn Monroe", "birthdate": "June 01, 1926"},
{"bio": "Anna Eleanor Roosevelt was an American political leader who used her influence as an active First Lady from 1933 to 1945 to promote the New Deal policies of her husband, President Franklin D. Roosevelt, as well as taking a prominent role as an advocate for civil rights. After her husband's death in 1945, she continued to be an internationally prominent author and speaker for the New Deal coalition. She was a suffragist who worked to enhance the status of working women, although she opposed the Equal Rights Amendment because she believed it would adversely affect women. In the 1940s, she was one of the co-founders of Freedom House and supported the formation of the United Nations. Eleanor Roosevelt founded the UN Association of the United States in 1943 to advance support for the formation of the UN. She was a delegate to the UN General Assembly from 1945 and 1952, a job for which she was appointed by President Harry S. Truman and confirmed by the United States Congress. During her time at the United Nations chaired the committee that drafted and approved the Universal Declaration of Human Rights. President Truman called her the \"First Lady of the World\" in tribute to her human rights achievements.She was one of the most admired persons of the 20th century, according to Gallup's List of Widely Admired People.", "name": "Eleanor Roosevelt", "birthdate": "October 11, 1884"},
...
]

虽然同一个author页可能会被访问多次,不过,Scrapy会过滤掉重复的请求以降低对服务器的压力。这个特性可以通过DUPEFILTER_CLASS参数配置。

给爬虫传递参数

可以用-a选项给爬虫传参数,比如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
scrapy crawl quotes -o quotes-humor.json -a tag=humor

这个参数会被传到爬虫的__init__方法里,称为爬虫的一个属性。

上面的参数会复制给爬虫的self.tag属性,我们可以利用这个属性,去爬取特定网页

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import scrapy


class QuotesSpider(scrapy.Spider):
    name = "quotes"

    def start_requests(self):
        url = 'http://quotes.toscrape.com/'
        tag = getattr(self, 'tag', None)
        if tag is not None:
            url = url + 'tag/' + tag
        yield scrapy.Request(url, self.parse)

    def parse(self, response):
        for quote in response.css('div.quote'):
            yield {
                'text': quote.css('span.text::text').extract_first(),
                'author': quote.css('small.author::text').extract_first(),
            }

        next_page = response.css('li.next a::attr(href)').extract_first()
        if next_page is not None:
            yield response.follow(next_page, self.parse)

比如传tag=humor,这爬虫就只爬取 http://quotes.toscrape.com/tag/humor

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
struts2标签示例
常用UI标签: Textfield标签输出一个HTML单行文本输入控件 Textarea标签输出一个HTML多行文本输入控件 Radio标签输出单选按钮 checkboxlist标签即复选框 file标签用于上传文件(accept属性,指出接受文件的MIME类型) Submit标签输出一个按钮 Select标签输出一个下拉列表框 doubleselect标签输出关联的两个HTML列表框,产生联动效果 updownselect标签创建一个带有上下移动的按钮的列表框 optiontransferselect标签
闵开慧
2018/03/30
1.1K0
Struts2 表单和非表单标签
上一章讲述了ognl和Struts2标签库中的数据访问标签和逻辑控制标签。本章将重点介绍Struts2标签库中的表单标签和非表单标签。
张哥编程
2024/12/17
3660
Struts2 表单和非表单标签
(19)Struts2_表单标签
表单标签 ---- 概述 表单标签将在 HTML 文档里被呈现为一个表单元素 使用表单标签的优点: 表单回显 对页面进行布局和排版 标签的属性可以被赋值为一个静态的值或一个 OGNL 表达式. 如果在
qubianzhong
2018/09/19
1.7K0
(19)Struts2_表单标签
struts2标签举例(完整运行程序)
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
闵开慧
2018/03/30
8220
Struts2【UI标签、数据回显、资源国际化】
Struts2UI标签 Sturts2为了简化我们的开发,也为我们提供了UI标签…也就是显示页面的标签….. 但是呢,Struts2是服务端的框架,因此使用页面的标签是需要在服务器端解析然后再被浏览器解析,最后才显示在页面上的。因此,它的性能是不够HTML标签好的…HTML直接就能够被浏览器解析 还有一点是:我们在写网页的时候,肯定是需要使用div+css的页面布局的。使用Struts2UI标签也没法干了….因此,除了有必要的话,才去使用Struts2UI标签 简单使用Struts2UI标签 <%--我们发
Java3y
2018/03/15
1K0
Struts2【UI标签、数据回显、资源国际化】
struts标签中的select
            <!-- Struts下拉列表标签: name="deptId" 下拉列表标签的名称(服务器根据这个名称获取选择的项的实际的值value值) headerKey 默认选择项的实际的值 headerValue 默认下拉列表显示的内容
HUC思梦
2020/09/03
1.5K0
CRM第二篇
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
海仔
2019/10/22
1.1K0
Jquery 常见案例
版权声明:本文为博主原创文章,未经博主允许不得转载。
DencyCheng
2018/11/05
7.6K0
Struts2第四天:Struts2的拦截器和标签库
n Interceptor:拦截器,拦截是客户端对Action的访问。更细粒度化的拦截。(拦截Action中的具体的方法)。
AlbertYang
2020/09/08
4160
struts2 标签全面解释
A: <s:a xhref=""></s:a>-----超链接,类似于html里的<a></a> <s:action name=""></s:action>-----执行一个view里面的一个action <s:actionerror/>-----如果action的errors有值那么显示出来 <s:actionmessage/>-----如果action的message有值那么显示出来 <s:append></s:append>-----添加一个值到list,类似于list.add(); <s:autoc
闵开慧
2018/03/30
1.2K0
【SSH测试整合Demo】企业人事管理系统
前言 前面我们已经学习了怎么整合SSH框架了。是时候拿一个小项目来练练手了….我们现在要设计一个企业人事管理系统… 需求: **要求对员工信息进行维护; ** 后台系统先登陆,才能操作员工: 添加/修改/删除 没有登陆,只能查看列表,不能操作! 功能分类: 【管理员模块】 注册/登陆 【员工模块】 1) 添加一个员工, 指定添加的部门 2) 对指定的员工信息修改 3) 删除选择员工 4) 列表展示 数据库设计 管理员表: t_admin 员工表: t_user 部门: t_dept ----
Java3y
2018/03/16
2.7K0
【SSH测试整合Demo】企业人事管理系统
几个表单操作(个人笔记)
单选按钮的三种写法: <!-- 方法1: %{ #{'男':'男','女':'女' } } : %{ognl表达式}; #{'男':'男','女':'女' } : #{ Map,Map } --> <s:radio name="gender" list="%{ #{'男':'男','女':'女' } }"></s:radio> <!-- 方法2: #{'男':'男','女':'女' } : ognl表达式 --> <s:radio name="gender" list=" #{'男'
Java架构师必看
2021/05/17
2550
day38_Spring学习笔记_06_CRM_02
注意:当前员工的职务所属的部门,此部门下的所有职务。代码表示:post.department.postSet editStaff.jsp
黑泽君
2018/10/11
1.6K0
day38_Spring学习笔记_06_CRM_02
Struts2 类型转换和数据校验
Struts 2提供了功能强大的类型转换器来处理表现层数据,开发者可以利用Struts 2的类型转换机制来完成任意的类型转换。在应用开发中,对用户的输入进行校验是经常遇到的业务,Struts 2提供了多种方式供开发者对客户输入的数据进行校验,非常得方便灵活。
张哥编程
2024/12/17
1420
Struts2  类型转换和数据校验
[ SSH框架 ] Struts2框架学习之四(自定义拦截器)
一、Struts2的拦截器 1.1 拦截器概述    拦截器,在AOP( Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。   在 Webwork的中文文档的解释为—拦截器是动态拦截 Action调用的对象。它提供了一种机制可以使开发者可以定义在一个 action执行的前后执行的代码,也可以在一个 action执行前阻止其执行。同时也是提供了一种可以提取 action中可重用的部分的方式。   谈到拦
Kevin_Zhang
2018/05/22
1.3K0
Struts2标签库和OGNL
前面我们编写的案例使用的都是HTML标签,这些标签并不能很好的与Struts 2框架结合,Struts 2和Struts 1一样都自带了功能强大、成熟完善的标签库供我们使用,通过使用这些标签库可以大大提高开发效率和代码的可维护性。
张哥编程
2024/12/17
1720
Struts2标签库和OGNL
深入理解Struts2----类型转换
Single
2018/01/04
2.3K0
深入理解Struts2----类型转换
Struts2 之 modelDriven & prepare 拦截器详解
struts2 ModelDriven & Prepareable 拦截器 前面对于 Struts2 的开发环境的搭建、配置文件以及 Struts2 的值栈都已经进行过叙述了!这次博文我们讲解利用 S
bgZyy
2018/07/05
9790
实用的JavaScript(持续添加)
Checkbox类: 1.实现checkbox的全选功能 <script type="text/javascript"> //全选checkbox:1、当全选checkbox勾选,子checkbox(name为'ids'的checkbox)自动全部勾选 // 2、当全选checkbox取消勾选,子checkbox自动全部取消勾选 function checkAll(){ if($("#checkall")[0].checked){ $("input[type='checkbox
Java架构师必看
2021/05/17
1.3K0
Struts2第二天:Struts2的数据的封装、结果页面配置
在使用Struts2的框架的过程中,发现Struts2和Servlet的API是解耦合的。在实际开发中,经常使用到Servlet的API,比如进行登录,将用户的信息保存到Session中,有的时候需要向页面输出一些内容,用到response对象。涉及到Servlet的API的访问。
AlbertYang
2020/09/08
5610
相关推荐
struts2标签示例
更多 >
目录
  • 创建一个Scrapy项目
  • 第一个爬虫
  • 让爬虫跑起来
    • 简化start_requests()
  • 解析数据
  • 正则表达式
  • XPath简介
  • 提取quote和author
  • 提取 title, author 和 tags
  • 在爬虫中提取数据
  • 存储数据
  • Following links
  • 简化scrapy.Request
  • 另一个例子
  • 给爬虫传递参数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档