章节十四:Scrapy框架
章节十四:Scrapy框架
1. Scrapy是什么
1.1 Scrapy的结构
1.2 Scrapy的工作原理
2. Scrapy的用法
2.1 明确目标与分析过程
2.2 代码实现——创建项目
2.3 代码实现——编辑爬虫
2.4 代码实现——定义数据
2.5 代码实操——设置
2.6 代码实操——运行
3. 代码实操
4. 复习
5. 习题练习
前两关,我们学习了能提升爬虫速度的进阶知识——协程,并且通过项目实操,将协程运用于抓取薄荷网的食物数据。
可能你在体验开发一个爬虫项目的完整流程时,会有这样的感觉:原来要完成一个完整的爬虫程序需要做这么多琐碎的工作。
比如,要导入不同功能的模块,还要编写各种爬取流程的代码。而且根据不同的项目,每次要编写的代码也不同。
不知道你会不会有这样的想法:能不能有一个现成的爬虫模板,让我们拿来就能套用,就像PPT模板一样。我们不需要管爬虫的全部流程,只要负责填充好爬虫的核心逻辑代码就好。要是有的话,我们编写代码一定会很方便省事。
其实,在Python中还真的存在这样的爬虫模板,只不过它的名字是叫框架。
一个爬虫框架里包含了能实现爬虫整个流程的各种模块,就像PPT模板一开始就帮你设置好了主题颜色和排版方式一样。
这一关,我们要学习的就是一个功能强大的爬虫框架——Scrapy。
1. Scrapy是什么
以前我们写爬虫,要导入和操作不同的模块,比如requests模块、gevent库、csv模块等。而在Scrapy里,你不需要这么做,因为很多爬虫需要涉及的功能,比如麻烦的异步,在Scrapy框架都自动实现了。
我们之前编写爬虫的方式,相当于在一个个地在拼零件,拼成一辆能跑的车。而Scrapy框架则是已经造好的、现成的车,我们只要踩下它的油门,它就能跑起来。这样便节省了我们开发项目的时间。
下面,我们来了解Scrapy的基础知识,包括Scrapy的结构及其工作原理。
1.1 Scrapy的结构
上面的这张图是Scrapy的整个结构。你可以把整个Scrapy框架看成是一家爬虫公司。最中心位置的Scrapy Engine(引擎)
就是这家爬虫公司的大boss,负责统筹公司的4大部门,每个部门都只听从它的命令,并只向它汇报工作。
我会以爬虫流程的顺序来依次跟你介绍Scrapy爬虫公司的4大部门。
Scheduler
(调度器)部门主要负责处理引擎发送过来的requests对象(即网页请求的相关信息集合,包括params,data,cookies,request headers…等),会把请求的url以有序的方式排列成队,并等待引擎来提取(功能上类似于gevent库的queue模块)。
Downloader
(下载器)部门则是负责处理引擎发送过来的requests,进行网页爬取,并将返回的response(爬取到的内容)交给引擎。它对应的是爬虫流程【获取数据】这一步。
Spiders
(爬虫)部门是公司的核心业务部门,主要任务是创建requests对象和接受引擎发送过来的response(Downloader部门爬取到的内容),从中解析并提取出有用的数据。它对应的是爬虫流程【解析数据】和【提取数据】这两步。
Item Pipeline
(数据管道)部门则是公司的数据部门,只负责存储和处理Spiders部门提取到的有用数据。这个对应的是爬虫流程【存储数据】这一步。
Downloader Middlewares
(下载中间件)的工作相当于下载器部门的秘书,比如会提前对引擎大boss发送的诸多requests做出处理。
Spider Middlewares
(爬虫中间件)的工作则相当于爬虫部门的秘书,比如会提前接收并处理引擎大boss发送来的response,过滤掉一些重复无用的东西。
1.2 Scrapy的工作原理
你会发现,在Scrapy爬虫公司里,每个部门都各司其职,形成了很高效的运行流程。
这套运行流程的逻辑很简单,就是:引擎大boss说的话就是最高需求。
上图展现出的也是Scrapy框架的工作原理——引擎是中心,其他组成部分由引擎调度。
在Scrapy里,整个爬虫程序的流程都不需要我们去操心,且Scrapy中的程序全部都是异步模式,所有的请求或返回的响应都由引擎自动分配去处理。
哪怕有某个请求出现异常,程序也会做异常处理,跳过报错的请求,继续往下运行程序。
在一定程度上,Scrapy可以说是非常让人省心的一套爬虫框架。
2. Scrapy的用法
现在,你已经初步了解Scrapy的结构以及工作原理。接下来,为了让你熟悉Scrapy的用法,我们使用它来完成一个小项目——爬取豆瓣Top250图书。
2.1 明确目标与分析过程
依旧是遵循写代码的三个步骤:明确目标、分析过程、代码实现来完成项目。我会在代码实现的步骤重点讲解Scrapy的用法。
首先,要明确目标。请你务必打开以下豆瓣Top250图书的链接。
https://book.douban.com/top250
豆瓣Top250图书一共有10页,每页有25本书籍。我们的目标是:先只爬取前三页书籍的信息,也就是爬取前75本书籍的信息(包含书名、出版信息和书籍评分)。
接着,我们来分析网页。既然我们要爬取书籍信息,我们就得先判断这些信息被存在了哪里。
判断的方法你应该了然于胸。赶紧右击打开“检查”工具,点开Network
,刷新页面,然后点击第0个请求top250
,看Response
.
我们能在里面翻找到书名、出版信息,说明我们想要的书籍信息就藏在这个网址的HTML里。
确定书籍信息有存在这个网址的HTML后,我们就来具体观察一下这个网站。
你点击翻到豆瓣Top250图书的第2页。
你会观察到,网址发生了变化,后面多了?start=25
。我们猜想,后面的数字是代表一页的25本书籍。
你可以翻到第3页,验证一下我们的猜想是不是正确的。
事实证明,我们猜对了。每翻一页,网址后面的数字都会增加25,说明这个start
的参数就是代表每页的25本书籍。
这么一观察,我们要爬取的网址的构造规律就出来了。只要改变?start=
后面的数字(翻一页加25),我们就能得到每一页的网址。
找到了网址的构造规律,我们可以重点来分析HTML的结构,看看等下怎么才能提取出我们想要的书籍信息。
仍旧是右击打开“检查”工具,点击Elements
,再点击光标,把鼠标依次移到书名、出版信息、评分处,就能在HTML里找到这些书籍信息。如下图,《追风筝的人》的书籍信息就全部放在标签里。
很快,你就会发现,其实每一页的25本书籍信息都分别藏在了一个标签里。不过这个标签没有class属性,也没有id属性,不方便我们提取信息。
我们得再找一个既方便我们提取,又能包含所有书籍信息的标签。
在标签下的元素刚好都能满足我们的要求,既有class属性,又包含了书籍的信息。
我们只要取出元素下
元素的title
属性的值、
元素、
元素,就能得到书名、出版信息和评分的数据。
页面分析完毕,接着进入代码实现的步骤。
2.2 代码实现——创建项目
从这里开始,我会带你使用Scrapy编写我们的项目爬虫。其中会涉及到很多Scrapy的用法,请你一定要认真地看!
提示:课程的终端已经安装好了Scrapy,如果你想着自己本地的电脑使用Scrapy,需要提前安装好它。(安装方法:Windows:在终端输入命令:pip install scrapy;mac:在终端输入命令:pip3 install scrapy,按下enter键)
首先,要在本地电脑打开终端(windows:Win+R,输入cmd;mac:command+空格,搜索“终端”),然后跳转到你想要保存项目的目录下。
假设你想跳转到E盘里名为Python文件夹中的Pythoncode子文件夹。你需要再命令行输入e:
,就会跳转到e盘,再输入cd Python
,就能跳转到Python文件夹。接着输入cd Pythoncode
,就能跳转到Python文件夹里的Pythoncode子文件夹。
然后,再输入一行能帮我们创建Scrapy项目的命令:scrapy startproject douban
,douban
就是Scrapy项目的名字。按下enter键,一个Scrapy项目就创建成功了。
点击这里
整个scrapy项目的结构,如下图所示:
Scrapy项目里每个文件都有特定的功能,比如settings.py 是scrapy里的各种设置。items.py是用来定义数据的,pipelines.py是用来处理数据的,它们对应的就是Scrapy的结构中的Item Pipeline(数据管道)。
现在或许你还看不懂它们,没关系,事情将会一点点变清晰。我们来讲解它们。
2.3 代码实现——编辑爬虫
如前所述,spiders是放置爬虫的目录。我们可以在spiders这个文件夹里创建爬虫文件。我们来把这个文件,命名为top250。后面的大部分代码都需要在这个top250.py文件里编写。
先在top250.py文件里导入我们需要的模块。
import scrapy
import bs4
导入BeautifulSoup
用于解析和提取数据,这个应该不需要我多做解释。在第3关、第4关的时候你就已经对它非常熟稔。
导入scrapy
是待会我们要用创建类的方式写这个爬虫,我们所创建的类将直接继承scrapy
中的scrapy.Spider
类。这样,有许多好用属性和方法,就能够直接使用。
接着我们开始编写爬虫的核心代码。
在Scrapy中,每个爬虫的代码结构基本都如下所示:
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['book.douban.com']
start_urls = ['https://book.douban.com/top250?start=0']
def parse(self, response):
print(response.text)
第1行代码:定义一个爬虫类DoubanSpider
。就像我刚刚讲过的那样,DoubanSpider
类继承自scrapy.Spider
类。
第2行代码:name
是定义爬虫的名字,这个名字是爬虫的唯一标识。name = 'douban'
意思是定义爬虫的名字为douban
。等会我们启动爬虫的时候,要用到这个名字。
第3行代码:allowed_domains
是定义允许爬虫爬取的网址域名(不需要加https://
)。如果网址的域名不在这个列表里,就会被过滤掉。
为什么会有这个设置呢?当你在爬取大量数据时,经常是从一个URL开始爬取,然后关联爬取更多的网页。比如,假设我们今天的爬虫目标不是爬书籍信息,而是要爬豆瓣图书top250的书评。我们会先爬取书单,再找到每本书的URL,再进入每本书的详情页面去抓取评论。
allowed_domains
就限制了,我们这种关联爬取的URL,一定在book.douban.com
这个域名之下,不会跳转到某个奇怪的广告页面。
第4行代码:start_urls
是定义起始网址,就是爬虫从哪个网址开始抓取。在此,allowed_domains
的设定对start_urls
里的网址不会有影响。
第6行代码:parse
是Scrapy里默认处理response的一个方法,中文是解析。
你或许会好奇,这里是不是少了一句类似requests.get()
这样的代码?的确是,在这里,我们并不需要写这一句。scrapy
框架会为我们代劳做这件事,写好你的请求,接下来你就可以直接写对响应如何做处理,我会在后面为你做示例。
了解完爬虫代码的基础结构,我们继续来完善爬取豆瓣Top图书的代码。
豆瓣Top250图书一共有10页,每一页的网址我们都知道。我们可以选择把10页网址都塞进start_urls
的列表里。
但是这样的方式并不美观,而且如果要爬取的是上百个网址,全部塞进start_urls
的列表里的话,代码就会非常长。
其实,我们可以利用豆瓣Top250图书的网址规律,用for循环构造出每个网址,再把网址添加进start_urls
的列表里。这样代码会美观得多。
完善后的代码如下:
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['book.douban.com']
start_urls = []
for x in range(3):
url = 'https://book.douban.com/top250?start=' + str(x * 25)
start_urls.append(url)
我们只先爬取豆瓣Top250前3页的书籍信息。
接下来,只要再借助parse方法处理response,借助BeautifulSoup来取出我们想要的书籍信息的数据,代码即可完成。
我们前面在分析项目过程的时候,已经知道书籍信息都藏在了哪些元素里,现在可以利用find_all和find方法提取出来。比如,书名是元素下
元素的title
属性的值;出版信息在
元素里;评分在
元素里。
按照过去的知识,我们可能会把代码写成这个模样:
import scrapy
import bs4
from ..items import DoubanItem
class DoubanSpider(scrapy.Spider):
#定义一个爬虫类DoubanSpider。
name = 'douban'
#定义爬虫的名字为douban。
allowed_domains = ['book.douban.com']
#定义爬虫爬取网址的域名。
start_urls = []
#定义起始网址。
for x in range(3):
url = 'https://book.douban.com/top250?start=' + str(x * 25)
start_urls.append(url)
#把豆瓣Top250图书的前3页网址添加进start_urls。
def parse(self, response):
#parse是默认处理response的方法。
bs = bs4.BeautifulSoup(response.text,'html.parser')
#用BeautifulSoup解析response。
datas = bs.find_all('tr',class_="item")
#用find_all提取元素,这个元素里含有书籍信息。
for data in datas:
#遍历data。
title = data.find_all('a')[1]['title']
#提取出书名。
publish = data.find('p',class_='pl').text
#提取出出版信息。
score = data.find('span',class_='rating_nums').text
#提取出评分。
print([title,publish,score])
#打印上述信息。
按照过去,我们会把书名、出版信息、评分,分别赋值,然后统一做处理——或是打印,或是存储。但在scrapy
这里,事情却有所不同。
spiders
(如top250.py)只干spiders
应该做的事。对数据的后续处理,另有人负责。
2.4 代码实现——定义数据
在scrapy中,我们会专门定义一个用于记录数据的类。
当我们每一次,要记录数据的时候,比如前面在每一个最小循环里,都要记录“书名”,“出版信息”,“评分”。我们会实例化一个对象,利用这个对象来记录数据。
每一次,当数据完成记录,它会离开spiders
,来到Scrapy Engine(引擎),引擎将它送入Item Pipeline(数据管道)处理。
定义这个类的py文件,正是items.py
。
我们已经知道,我们要爬取的数据是书名、出版信息和评分,我们来看看如何在items.py里定义这些数据。代码如下:
import scrapy
#导入scrapy
class DoubanItem(scrapy.Item):
#定义一个类DoubanItem,它继承自scrapy.Item
title = scrapy.Field()
#定义书名的数据属性
publish = scrapy.Field()
#定义出版信息的数据属性
score = scrapy.Field()
#定义评分的数据属性
第1行代码,我们导入了scrapy。目的是,我们等会所创建的类将直接继承scrapy
中的scrapy.Item
类。这样,有许多好用属性和方法,就能够直接使用。比如到后面,引擎能将item类的对象发给Item Pipeline(数据管道)处理。
第3行代码:我们定义了一个DoubanItem类。它继承自scrapy.Item类。
第5、7、9行代码:我们定义了书名、出版信息和评分三种数据。scrapy.Field()
这行代码实现的是,让数据能以类似字典的形式记录。你可能不太明白这句话的含义,没关系。我带你来体验一下,你就能感受到是怎样一回事:
import scrapy
#导入scrapy
class DoubanItem(scrapy.Item):
#定义一个类DoubanItem,它继承自scrapy.Item
title = scrapy.Field()
#定义书名的数据属性
publish = scrapy.Field()
#定义出版信息的数据属性
score = scrapy.Field()
#定义评分的数据属性
book = DoubanItem()
# 实例化一个DoubanItem对象
book['title'] = '海边的卡夫卡'
book['publish'] = '[日] 村上春树 / 林少华 / 上海译文出版社 / 2003'
book['score'] = '8.1'
print(book)
print(type(book))
你会看到打印出来的结果的确和字典非常相像,但它却并不是dict,它的数据类型是我们定义的DoubanItem,属于“自定义的Python字典”。我们可以利用类似上述代码的样式,去重新写top250.py。如下所示:
import scrapy
import bs4
from ..items import DoubanItem
# 需要引用DoubanItem,它在items里面。因为是items在top250.py的上一级目录,所以要用..items,这是一个固定用法。
class DoubanSpider(scrapy.Spider):
#定义一个爬虫类DoubanSpider。
name = 'douban'
#定义爬虫的名字为douban。
allowed_domains = ['book.douban.com']
#定义爬虫爬取网址的域名。
start_urls = []
#定义起始网址。
for x in range(3):
url = 'https://book.douban.com/top250?start=' + str(x * 25)
start_urls.append(url)
#把豆瓣Top250图书的前3页网址添加进start_urls。
def parse(self, response):
#parse是默认处理response的方法。
bs = bs4.BeautifulSoup(response.text,'html.parser')
#用BeautifulSoup解析response。
datas = bs.find_all('tr',class_="item")
#用find_all提取元素,这个元素里含有书籍信息。
for data in datas:
#遍历data。
item = DoubanItem()
#实例化DoubanItem这个类。
item['title'] = data.find_all('a')[1]['title']
#提取出书名,并把这个数据放回DoubanItem类的title属性里。
item['publish'] = data.find('p',class_='pl').text
#提取出出版信息,并把这个数据放回DoubanItem类的publish里。
item['score'] = data.find('span',class_='rating_nums').text
#提取出评分,并把这个数据放回DoubanItem类的score属性里。
print(item['title'])
#打印书名。
yield item
#yield item是把获得的item传递给引擎。
在3行,我们需要引用DoubanItem,它在items里面。因为是items在top250.py的上一级目录,所以要用..items,这是一个固定用法。
当我们每一次,要记录数据的时候,比如前面在每一个最小循环里,都要记录“书名”,“出版信息”,“评分”。我们会实例化一个item
对象,利用这个对象来记录数据。
每一次,当数据完成记录,它会离开spiders
,来到Scrapy Engine(引擎),引擎将它送入Item Pipeline(数据管道)处理。这里,要用到yield
语句。
yield
语句你可能还不太了解,这里你可以简单理解为:它有点类似return,不过它和return不同的点在于,它不会结束函数,且能多次返回信息。
如果用可视化的方式来呈现程序运行的过程,就如同上图所示:爬虫(Spiders)会把豆瓣的10个网址封装成requests对象,引擎会从爬虫(Spiders)里提取出requests对象,再交给调度器(Scheduler),让调度器把这些requests对象排序处理。
然后引擎再把经过调度器处理的requests对象发给下载器(Downloader),下载器会立马按照引擎的命令爬取,并把response返回给引擎。
紧接着引擎就会把response发回给爬虫(Spiders),这时爬虫会启动默认的处理response的parse方法,解析和提取出书籍信息的数据,使用item做记录,返回给引擎。引擎将它送入Item Pipeline(数据管道)处理。
2.5 代码实操——设置
到这里,我们就用代码编写好了一个爬虫。不过,实际运行的话,可能还是会报错。
原因在于Scrapy里的默认设置没被修改。比如我们需要修改请求头。点击settings.py文件,你能在里面找到如下的默认设置代码:
# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'douban (+http://www.yourdomain.com)'
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
请你把USER _AGENT
的注释取消(删除#),然后替换掉user-agent的内容,就是修改了请求头。
又因为Scrapy是遵守robots协议的,如果是robots协议禁止爬取的内容,Scrapy也会默认不去爬取,所以我们还得修改Scrapy中的默认设置。
把ROBOTSTXT_OBEY=True
改成ROBOTSTXT_OBEY=False
,就是把遵守robots协议换成无需遵从robots协议,这样Scrapy就能不受限制地运行。
修改后的代码应该如下所示:
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
现在,我们已经编写好了spider,也修改好了setting。万事俱备,只欠东风——运行Scrapy。
2.6 代码实操——运行
想要运行Scrapy有两种方法,一种是在本地电脑的终端跳转到scrapy项目的文件夹(跳转方法:cd+文件夹的路径名),然后输入命令行:scrapy crawl douban
(douban 就是我们爬虫的名字)。
点击这里
另一种运行方式需要我们在最外层的大文件夹里新建一个main.py文件(与scrapy.cfg同级)。
我们只需要在这个main.py文件里,输入以下代码,点击运行,Scrapy的程序就会启动。
from scrapy import cmdline
#导入cmdline模块,可以实现控制终端命令行。
cmdline.execute(['scrapy','crawl','douban'])
#用execute()方法,输入运行scrapy的命令。
第1行代码:在Scrapy中有一个可以控制终端命令的模块cmdline。导入了这个模块,我们就能操控终端。
第3行代码:在cmdline模块中,有一个execute方法能执行终端的命令行,不过这个方法需要传入列表的参数。我们想输入运行Scrapy的代码scrapy crawl douban
,就需要写成['scrapy','crawl','douban']
这样。
至此,Scrapy的用法我们学完啦。
值得一提的是,在本关卡中为了教学方便理解,先写了爬虫,再定义数据。但是,在实际项目实战中,常常顺序却是相反的——先定义数据,再写爬虫。所以,流程图应如下:
细心的你可能会发现,这一关的内容没有涉及到存储数据的步骤。
是的,存储数据需要修改pipelines.py文件。这一关的内容已经很充实,所以这个知识点我们留到下一关再讲。
最后,是这一关的重点知识的复习。
3. 代码实操
top250.py
(在spiders文件下)的基本代码结构示例:
#在spiders文件下
import scrapy
import bs4
from ..items import DoubanItem
# 需要引用DoubanItem,它在items里面。因为是items在top250.py的上一级目录,所以要用..items,这是一个固定用法。
class DoubanSpider(scrapy.Spider):
#定义一个爬虫类DoubanSpider。
name = 'douban'
#定义爬虫的名字为douban。
allowed_domains = ['book.douban.com']
#定义爬虫爬取网址的域名。
start_urls = []
#定义起始网址。
for x in range(3):
url = 'https://book.douban.com/top250?start=' + str(x * 25)
start_urls.append(url)
#把豆瓣Top250图书的前3页网址添加进start_urls。
def parse(self, response):
#parse是默认处理response的方法。
bs = bs4.BeautifulSoup(response.text,'html.parser')
#用BeautifulSoup解析response。
datas = bs.find_all('tr',class_="item")
#用find_all提取元素,这个元素里含有书籍信息。
for data in datas:
#遍历data。
item = DoubanItem()
#实例化DoubanItem这个类。
item['title'] = data.find_all('a')[1]['title']
#提取出书名,并把这个数据放回DoubanItem类的title属性里。
item['publish'] = data.find('p',class_='pl').text
#提取出出版信息,并把这个数据放回DoubanItem类的publish里。
item['score'] = data.find('span',class_='rating_nums').text
#提取出评分,并把这个数据放回DoubanItem类的score属性里。
print(item['title'])
#打印书名。
yield item
#yield item是把获得的item传递给引擎。
定义items.py
(与spiders文件同级)的代码示例:
import scrapy
#导入scrapy
class DoubanItem(scrapy.Item):
#定义一个类DoubanItem,它继承自scrapy.Item
title = scrapy.Field()
#定义书名的数据属性
publish = scrapy.Field()
#定义出版信息的数据属性
score = scrapy.Field()
#定义评分的数据属性
修改setting.py
(与spiders文件同级)文件
#修改前的默认设置
# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'douban (+http://www.yourdomain.com)'
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
#修改后的设置
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
4)运行main.py
(与spiders文件同级)的代码示例:
from scrapy import cmdline
#导入cmdline模块,可以实现控制终端命令行。
cmdline.execute(['scrapy','crawl','douban'])
#用execute()方法,输入运行scrapy的命令。
5)运行结果
4. 复习
Scrapy的结构——
Scrapy的工作原理——
Scrapy的用法——
5. 习题练习
1.要求: 请使用Scrapy,爬取当当网2018年图书销售榜单前3页的数据(图书名、作者和书的价格)。
当当网2018年图书销售榜单链接:http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-year-2018-0-1-1
2.目的: 1)练习定义item 2)练习编写spiders文件 3)练习修改settings文件
3.知识点回顾
1)定义item的代码示例:
import scrapy
#导入scrapy
class DoubanItem(scrapy.Item):
#定义一个类DoubanItem,它继承自scrapy.Item
title = scrapy.Field()
#定义书名的数据属性
publish = scrapy.Field()
#定义出版信息的数据属性
score = scrapy.Field()
#定义评分的数据属性
2)spider的基本代码结构示例:
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['book.douban.com']
start_urls = ['https://book.douban.com/top250?start=0']
def parse(self, response):
print(response.text)
3)修改setting文件
#修改前的默认设置
# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'douban (+http://www.yourdomain.com)'
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
#修改后的设置
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
4)运行scrapy的代码示例:
from scrapy import cmdline
cmdline.execute(['scrapy','crawl','douban'])
4.执行结果
你可能感兴趣的:(scrapy,爬虫,python,开发语言)
python中的dict与set
“光光”
python
python内置字典:dict支持key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样取出来的时候才能根据key拿到value。由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会将前面的值覆盖掉。如果key不存在,dict就会报错要避免key不存在的错误,有两种方法:1)通过in判断key是否存在>>>d={'a':'1'}>
Python基础---Dict(字典)
grace666
Python
1.字典以键值对组成,包含在{}中,字典的键必须为hashable,即不可变(字符串、元组、数字),并且唯一;值可以是任何类型#dict1={[1]:1}#报错:TypeError:unhashabletype:'list'#dict1={{1}:1}#报错:TypeError:unhashabletype:'set'dict1={(1,):1}print(dict1)#{(1,):1}dict1
Markdown 到 PowerPoint 转换工具——md2pptx
伍盛普Silas
Markdown到PowerPoint转换工具——md2pptxmd2pptxMarkdownToPowerPointconverter项目地址:https://gitcode.com/gh_mirrors/md/md2pptxmd2pptx是一个开源项目,它可以将Markdown格式的文本转换为PowerPoint演示文稿。该项目主要使用Python编程语言实现。项目基础介绍md2pptx是一个
Python网络爬虫-WebSocket数据抓取
程序小勇
faiss 爬虫 python 网络协议 websocket 开发语言
目录前言1、WebSocket请求的分析通常涉及以下几个方面:2、利用WebSocket爬取数据总结最后,创作不易!非常感谢大家的关注、点赞、评论啦!谢谢三连哦!好人好运连连,学习进步!工作顺利哦!博主介绍:✌专注于前后端、机器学习、人工智能应用领域开发的优质创作者、秉着互联网精神开源贡献精神,答疑解惑、坚持优质作品共享。本人是掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战,
python 山脊图_(数据科学学习手札98)纯Python绘制满满艺术感的山脊地图
weixin_39780255
python 山脊图
1简介下面的这幅图可能很多读者朋友们都看到过,这是英国摇滚乐队JoyDivision在1979年发行的其第一张录音室专辑UnknownPleasures的封面,由艺术家PeterSaville基于射电脉冲星信号的数据图创作而成,成为了一种流行文化的符号标志。图1类似图1的风格,在地图制作中也存在着一种山脊地图,基于记录地表海拔信息的高程数据,我们可以利用水平方向上的基于实际位置海拔高度的曲线,来对
【Python 学习 / 5】函数详解(定义、参数、作用域、lambda、内置函数)
卜及中
Python基础 python 学习 开发语言
文章目录一、函数1.定义函数1.1基本函数定义1.2带参数的函数1.3带返回值的函数2.参数传递2.1位置参数2.2默认参数2.3可变参数2.3.1使用`*args`2.3.2使用`**kwargs`2.4参数的混合使用3.作用域3.1局部和全局变量3.2`global`关键字输出:3.3`nonlocal`关键字输出:4.lambda表达式4.1基本用法4.2与`map()`、`filter()
leetcode简单(181-200)python
九日火
leetcode python
762.PrimeNumberofSetBitsinBinaryRepresentation(e-181)GiventwointegersLandR,findthecountofnumbersintherange[L,R](inclusive)havingaprimenumberofsetbitsintheirbinaryrepresentation.(Recallthatthenumberofs
PaddleOCR面板恢复python脚本--针对pdf的面板恢复
zsh669
paddlepaddle ocr 百度 python pdf
问题在做一个项目的时候,使用PaddleOCR提供的模型,实现对图片或者pdf进行面板恢复,并保存为.docx文档。但是,官方的文档只提供了针对图片进行面板恢复的python脚本,没有提供pdf进行面板恢复的python脚本,官方只提供了pdf面板恢复的命令行使用方法,因此,我去看了PaddleOCR的源码,将命令行方法转换为python脚本准备工作环境配置和文档请参考:\ppstructure/
Python库 - transformers
司南锤
PYTHON库 python机器学习 python 开发语言
transformers库是由HuggingFace开发的一个非常流行的Python库,用于自然语言处理(NLP)任务。它提供了大量的预训练模型,这些模型可以用于各种NLP任务,如文本分类、问答、翻译、摘要生成等。以下是关于transformers库的详细介绍:1.主要特点预训练模型:transformers库包含了多种预训练的语言模型,如BERT、GPT、T5、XLNet等。这些模型在大规模文本
【NLP-04】tranformers库保姆级使用教程---以BERT模型为例
云天徽上
NLP bert 人工智能 深度学习 自然语言处理 机器学习 numpy 信息可视化
安装要安装一个非常轻量级的Transformers库,您可以执行以下步骤:1、打开终端或命令提示符。2、运行以下命令来安装Transformers库:pipinstalltransformers这将使用pip工具从PythonPackageIndex(PyPI)下载并安装Transformers库。请确保您的计算机上已经安装了pip。然后,您可以在Python代码中导入Transformers库:
利用 OpenCV 进行棋盘检测与透视变换
萧鼎
python基础到进阶教程 opencv 人工智能 计算机视觉
利用OpenCV进行棋盘检测与透视变换1.引言在计算机视觉领域,棋盘检测与透视变换是一个常见的任务,广泛应用于摄像机标定、文档扫描、增强现实(AR)等场景。本篇文章将详细介绍如何使用OpenCV进行棋盘检测,并通过透视变换将棋盘区域转换为一个标准的矩形图像。我们将基于一段Python代码进行分析,代码的主要任务包括:读取图像并进行预处理(灰度转换、自适应直方图均衡化、去噪)检测边缘并提取棋盘区域计
conda更换环境版本(比如torch版本)
挨打且不服66
python python
找到想要的torch版本pytorch官网torch过往的版本创建新环境condacreate--namemyenvpython=3.8condaactivatemyenvconda虚拟环境中安装CUDA和CUDNN深度学习用显卡训练的时候,需要安装与显卡对应的cuda和cudnn。但不同的项目所支持的pytorch版本是不一样的,而pytorch版本和cuda版本之间又是互相依赖的,所以如果可以
流行编程语言全解析:优势、应用与短板
a小胡哦
python java c++ c语言 javascript swift r语言
Python:优势Python以其简洁、易读的语法闻名,新手能快速上手。丰富的库和框架,能极大地提高开发效率。适用领域数据科学与分析:处理和分析大规模数据集,进行数据可视化。典型示例:Google用Python进行数据分析,处理海量数据以支持各种业务决策。机器学习与人工智能:构建和训练模型。典型示例:OpenAI在很多人工智能项目中广泛使用Python,如GPT系列模型的研发。网络爬虫:轻松从网页
用conda虚拟环境解决py+torch环境问题
SevenZS
Note anaconda python
要事先安装wheelpipinstallwheelcondainstallnb_conda安装nb_conda这样可以在shell切换虚拟环境启动jupyternotebook后切换到虚拟环境创建虚拟环境condacreate-npython36python=3.6condaactivatepython36加载后再pip安装torch1.4+cu101所有版本torch放在某个文件夹,比如桌面后p
【报错】ImportError: cannot import name ‘get_refined_artifact_map‘ from ‘basicsr.losses.loss_util‘
之群害马
python 深度学习 pytorch
ImportError:cannotimportname'get_refined_artifact_map'from'basicsr.losses.loss_util'(xxx/lib/python3.10/site-packages/basicsr/losses/loss_util.py)解决办法:找到basicsr库网站缺失的部分如下,补充到原来的xxx/lib/python3.10/site
Python 用pytorch从头写Transformer源码,一行一解释;机器翻译实例代码;Transformer源码解读与实战
医学小达人
NLP LLMs GPT 深度学习 人工智能 transformer python 机器学习
1.Transformer简介Transformer模型被提出的主要动机是解决序列处理任务的长距离依赖问题。传统的RNN和LSTM虽然能够处理序列任务,但因为它们在处理序列时需要一步步前进,因此其他信息无法立即对其产生影响,当序列变长时,长距离依赖的信息很可能会被丢失。为了解决这个问题,Transformer模型被设计出来,内核思想是利用自注意力机制,这样模型可以直接对输入序列的任意两个位置建立直
python正则表达式快速入门_Python 正则表达式入门
weixin_39955938
python正则表达式快速入门
本文主要为没有使用正则表达式经验的新手入门所写。转载请写明出处引子首先说正则表达式是什么?正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:RegularExpression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那
python正则表达式必知必会的基础
豆子前端
python基础 python 正则表达式
文章目录正则表达式re.match()和re.search()SRE_Matchobjectre.match()re.search()(重点)re.flags小结re.sub()re.split()re.findall()re.fullmatch()re.compile()小结方法分类注意细节正则表达式网站参考资料正则表达式本文主要讲的是正则表达式在python中的简单使用,只介绍关键的几个方法函
在conda虚拟环境中安装jupyter lab-----deepseek问答记录
溯源006
deepseek回答记录 conda jupyter ide
在Conda虚拟环境中安装JupyterLab的步骤如下:1.创建并激活Conda虚拟环境如果你还没有创建虚拟环境,可以使用以下命令创建一个新的虚拟环境并激活它:condacreate-nmyenvpython=3.x#将`myenv`替换为你的环境名称,`3.x`替换为所需的Python版本condaactivatemyenv2.安装JupyterLab在激活的虚拟环境中,使用以下命令安装Jup
单片机、嵌入式Linux开发大学自学路径
Oriental Son
嵌入式 MCU 单片机 单片机 学习 stm32 mcu linux
笔者所修读的专业为物联网工程,物联网工程是一门新兴的、热门的专业,其所涉及的学科更是又多又杂,既有计算机方向的编程语言(如C、C++、Java、Python等)、数据结构与算法、操作系统、移动端应用开发、机器学习等;软硬结合的方向有数字电路单片机开发、嵌入式Linux开发等;硬件、电路方向有电路分析、数字电路、模拟电路、传感器原理、RFID、FPGA开发等;涉及信号处理的有信号与系统、通信原理等。
深入解析 Poetry:Python 项目依赖管理的新宠,安装、使用及最佳实践
潘智祥
python java 人工智能
在Python的世界里,管理项目依赖和虚拟环境一直是一个令人头疼的问题。虽然有pip和virtualenv这样的工具,但随着项目的复杂性增加,它们的局限性也逐渐显露出来。这时候,Poetry作为一个现代化的依赖管理工具应运而生。它不仅解决了项目依赖管理的问题,同时也集成了虚拟环境管理、发布等功能,成为了Python开发者的新宠。Poetry是什么?Poetry是一个用于管理Python项目依赖和构
【JAVA工程师从0开始学AI】,第二步:从强类型到动态语言:Java工程师的Python语法避坑指南
架构默片
JAVA工程师从0开始学AI python java windows
这是一篇介绍Python语法与JAVA语法区别文章,让我们以对比的方式,来学习一下Python的语法。首先我们看一下下面的Python代码,和具体在java当中分别代表了什么意思numbers=[1,2,3,4,5,6,7,8,9]#①创建数字列表(像Java的ArrayList,但不用写泛型)odd_numbers=[]#②准备装奇数的空列表(类似Java的newArrayListnumbers
052_爬虫_爬虫相关概念(引用《尚硅谷Python爬虫教程(小)小 白零基础速通》052章)
一个有趣的昵称
python 爬虫 开发语言
爬虫解释:通过程序,根据url(http://taobao.com)进行网页的爬取获取有用的信息实用程序模拟浏览器,去向服务发送请求,获取响应信息爬虫的核心爬取网页:爬取整个网页包含了网页中所的内容解析数据:将网页中得到的数据进行解析难点:爬虫和但爬虫之间的博弈爬虫的类型实例通用爬虫百度,360,Google,搜狗等搜索引擎功能访问网页-》抓取数据-》数据储存-》数据处理-》提供检索服务robot
为一位经验丰富的程序员量身定制Python学习路线 人工智能首选语言:python Python新技术
小黄人软件
chatGPT python 学习 人工智能
人工智能首选语言:python必学。解释型语言(无编译这个环节),直接执行代码,面向对象,脚本语言没基础在这里学为一位经验丰富的程序员量身定制Python学习路线,主要应关注于深化已有的编程知识和技能,并探索Python特有的高级特性。以下是推荐的学习路线:基础复习:如果对Python基础不熟悉,先从Python的基础语法、数据类型、控制流程等开始复习。高级语言特性:深入理解装饰器、上下文管理器、
强化学习:原理、概念与代码实践
AndrewHZ
深度学习新浪潮 人工智能 深度学习 强化学习 机器学习 算法 deepseek
一、引言强化学习(ReinforcementLearning)作为机器学习的一个重要分支,旨在通过智能体(agent)与环境的交互,学习到最优的行为策略,以最大化长期累积奖励。它在机器人控制、游戏、自动驾驶、资源管理等众多领域都取得了显著的成功。本文将深入介绍强化学习的数学原理、核心概念,并通过公式推导来加深理解,同时结合一个具体的实例,使用Python语言进行代码实现,帮助读者全面掌握强化学习的
【Python基础】Python闭包:如何让你的代码拥有‘读心术’?
陈序不懂程序
python 服务器 apache 网络 开发语言 数据库 学习
第1章闭包概念与背景1.1闭包定义与理论基础闭包,这一术语源自数学逻辑,如今在计算机科学中占据着核心地位,尤其在面向对象和函数式编程领域中发挥着无可替代的作用。它是一种特殊的函数对象,不仅包含自身的代码逻辑,还携带着其定义时所处环境的部分状态,即对外部自由变量的引用。这种独特的“携带状态”特性赋予了闭包强大的功能和灵活性,使其成为实现抽象、封装、数据隐藏以及控制程序执行的关键工具。1.1.1闭包的
python学习 列表 字典 集合 面对对象编程 闭包 装饰器 函数式编程 作用域 异常处理
Scikit-learn
机器学习 python 算法 python 学习 开发语言
SIGIA_4Ppython学习列表字典集合面对对象编程闭包装饰器函数式编程作用域异常处理本文连接简介SIGIA_4P网址a.课程OKRObjectivesandKeyResults即目标与关键成果法目标,Objectives:掌握AI领域的Python开发成果1KR1linux目录结构[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r864ykpN-16917885
尚硅谷爬虫note007
CSDNy666999
爬虫
一、urllib—异常1.urllib.error.HTTPError2.urllib.error.URLError#_*_coding:utf-8_*_#@Time:2025/2/1411:33#@Author:20250206-里奥#@File:demo26_异常#@Project:PythonProject10-14importurllib.requestimporturllib.error
【JAVA工程师从0开始学AI】,第四步:闭包与高阶函数——用Python的“魔法函数“重构Java思维
架构默片
JAVA工程师从0开始学AI 人工智能 java python
副标题:当严谨的Java遇上"七十二变"的Python函数式编程历经变量战争、语法迷雾、函数对决,此刻我们将踏入Python最迷人的领域——函数式编程。当Java工程师还在用接口和匿名类实现回调时,Python的闭包已化身"智能机器人",带着"记忆传承"的能力自由穿梭于代码之间。这里没有类的枷锁,函数既是武器又是盾牌,高阶函数组合出的"代码万花筒",正是AI数据处理、模型训练的核心密码。本文将用J
【蓝桥杯集训·每日一题2025】 AcWing 6122. 农夫约翰的奶酪块 python
查理零世
蓝桥杯 python 算法
Week12月17日农夫约翰的奶酪块农夫约翰有一块立方体形状的奶酪,它位于三维坐标空间中,从(0,0,0)(0,0,0)(0,0,0)延伸至(N,N,N)(N,N,N)(N,N,N)。农夫约翰将对他的奶酪块执行一系列QQQ次更新操作。对于每次更新操作,农夫约翰将从整数坐标(x,y,z)(x,y,z)(x,y,z)到(x+1,y+1,z+1)(x+1,y+1,z+1)(x+1,y+1,z+1)处切割
集合框架
天子之骄
java 数据结构 集合框架
集合框架
集合框架可以理解为一个容器,该容器主要指映射(map)、集合(set)、数组(array)和列表(list)等抽象数据结构。
从本质上来说,Java集合框架的主要组成是用来操作对象的接口。不同接口描述不同的数据类型。
简单介绍:
Collection接口是最基本的接口,它定义了List和Set,List又定义了LinkLi
Table Driven(表驱动)方法实例
bijian1013
java enum Table Driven 表驱动
实例一:
/**
* 驾驶人年龄段
* 保险行业,会对驾驶人的年龄做年龄段的区分判断
* 驾驶人年龄段:01-[18,25);02-[25,30);03-[30-35);04-[35,40);05-[40,45);06-[45,50);07-[50-55);08-[55,+∞)
*/
public class AgePeriodTest {
//if...el
Jquery 总结
cuishikuan
java jquery Ajax Web jquery方法
1.$.trim方法用于移除字符串头部和尾部多余的空格。如:$.trim(' Hello ') // Hello2.$.contains方法返回一个布尔值,表示某个DOM元素(第二个参数)是否为另一个DOM元素(第一个参数)的下级元素。如:$.contains(document.documentElement, document.body); 3.$
面向对象概念的提出
麦田的设计者
java 面向对象 面向过程
面向对象中,一切都是由对象展开的,组织代码,封装数据。
在台湾面向对象被翻译为了面向物件编程,这充分说明了,这种编程强调实体。
下面就结合编程语言的发展史,聊一聊面向过程和面向对象。
c语言由贝尔实
linux网口绑定
被触发
linux
刚在一台IBM Xserver服务器上装了RedHat Linux Enterprise AS 4,为了提高网络的可靠性配置双网卡绑定。
一、环境描述
我的RedHat Linux Enterprise AS 4安装双口的Intel千兆网卡,通过ifconfig -a命令看到eth0和eth1两张网卡。
二、双网卡绑定步骤:
2.1 修改/etc/sysconfig/network
XML基础语法
肆无忌惮_
xml
一、什么是XML?
XML全称是Extensible Markup Language,可扩展标记语言。很类似HTML。XML的目的是传输数据而非显示数据。XML的标签没有被预定义,你需要自行定义标签。XML被设计为具有自我描述性。是W3C的推荐标准。
二、为什么学习XML?
用来解决程序间数据传输的格式问题
做配置文件
充当小型数据库
三、XML与HTM
为网页添加自己喜欢的字体
知了ing
字体 秒表 css
@font-face {
font-family: miaobiao;//定义字体名字
font-style: normal;
font-weight: 400;
src: url('font/DS-DIGI-e.eot');//字体文件
}
使用:
<label style="font-size:18px;font-famil
redis范围查询应用-查找IP所在城市
矮蛋蛋
redis
原文地址:
http://www.tuicool.com/articles/BrURbqV
需求
根据IP找到对应的城市
原来的解决方案
oracle表(ip_country):
查询IP对应的城市:
1.把a.b.c.d这样格式的IP转为一个数字,例如为把210.21.224.34转为3524648994
2. select city from ip_
输入两个整数, 计算百分比
alleni123
java
public static String getPercent(int x, int total){
double result=(x*1.0)/(total*1.0);
System.out.println(result);
DecimalFormat df1=new DecimalFormat("0.0000%");
百合——————>怎么学习计算机语言
百合不是茶
java 移动开发
对于一个从没有接触过计算机语言的人来说,一上来就学面向对象,就算是心里上面接受的了,灵魂我觉得也应该是跟不上的,学不好是很正常的现象,计算机语言老师讲的再多,你在课堂上面跟着老师听的再多,我觉得你应该还是学不会的,最主要的原因是你根本没有想过该怎么来学习计算机编程语言,记得大一的时候金山网络公司在湖大招聘我们学校一个才来大学几天的被金山网络录取,一个刚到大学的就能够去和
linux下tomcat开机自启动
bijian1013
tomcat
方法一:
修改Tomcat/bin/startup.sh 为:
export JAVA_HOME=/home/java1.6.0_27
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export PATH=$JAVA_HOME/bin:$PATH
export CATALINA_H
spring aop实例
bijian1013
java spring AOP
1.AdviceMethods.java
package com.bijian.study.spring.aop.schema;
public class AdviceMethods {
public void preGreeting() {
System.out.println("--how are you!--");
}
}
2.beans.x
[Gson八]GsonBuilder序列化和反序列化选项enableComplexMapKeySerialization
bit1129
serialization
enableComplexMapKeySerialization配置项的含义
Gson在序列化Map时,默认情况下,是调用Key的toString方法得到它的JSON字符串的Key,对于简单类型和字符串类型,这没有问题,但是对于复杂数据对象,如果对象没有覆写toString方法,那么默认的toString方法将得到这个对象的Hash地址。
GsonBuilder用于
【Spark九十一】Spark Streaming整合Kafka一些值得关注的问题
bit1129
Stream
包括Spark Streaming在内的实时计算数据可靠性指的是三种级别:
1. At most once,数据最多只能接受一次,有可能接收不到
2. At least once, 数据至少接受一次,有可能重复接收
3. Exactly once 数据保证被处理并且只被处理一次,
具体的多读几遍http://spark.apache.org/docs/lates
shell脚本批量检测端口是否被占用脚本
ronin47
#!/bin/bash
cat ports |while read line
do#nc -z -w 10 $line
nc -z -w 2 $line 58422>/dev/null2>&1if[ $?-eq 0]then
echo $line:ok
else
echo $line:fail
fi
done
这里的ports 既可以是文件
java-2.设计包含min函数的栈
bylijinnan
java
具体思路参见:http://zhedahht.blog.163.com/blog/static/25411174200712895228171/
import java.util.ArrayList;
import java.util.List;
public class MinStack {
//maybe we can use origin array rathe
Netty源码学习-ChannelHandler
bylijinnan
java netty
一般来说,“有状态”的ChannelHandler不应该是“共享”的,“无状态”的ChannelHandler则可“共享”
例如ObjectEncoder是“共享”的, 但 ObjectDecoder 不是
因为每一次调用decode方法时,可能数据未接收完全(incomplete),
它与上一次decode时接收到的数据“累计”起来才有可能是完整的数据,是“有状态”的
p
java生成随机数
cngolon
java
方法一:
/**
* 生成随机数
* @author
[email protected]
* @return
*/
public synchronized static String getChargeSequenceNum(String pre){
StringBuffer sequenceNum = new StringBuffer();
Date dateTime = new D
POI读写海量数据
ctrain
海量数据
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming
mysql 日期格式化date_format详细使用
daizj
mysql date_format 日期格式转换 日期格式化
日期转换函数的详细使用说明
DATE_FORMAT(date,format) Formats the date value according to the format string. The following specifiers may be used in the format string. The&n
一个程序员分享8年的开发经验
dcj3sjt126com
程序员
在中国有很多人都认为IT行为是吃青春饭的,如果过了30岁就很难有机会再发展下去!其实现实并不是这样子的,在下从事.NET及JAVA方面的开发的也有8年的时间了,在这里在下想凭借自己的亲身经历,与大家一起探讨一下。
明确入行的目的
很多人干IT这一行都冲着“收入高”这一点的,因为只要学会一点HTML, DIV+CSS,要做一个页面开发人员并不是一件难事,而且做一个页面开发人员更容
android欢迎界面淡入淡出效果
dcj3sjt126com
android
很多Android应用一开始都会有一个欢迎界面,淡入淡出效果也是用得非常多的,下面来实现一下。
主要代码如下:
package com.myaibang.activity;
import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.os.CountDown
linux 复习笔记之常见压缩命令
eksliang
tar解压 linux系统常见压缩命令 linux压缩命令 tar压缩
转载请出自出处:http://eksliang.iteye.com/blog/2109693
linux中常见压缩文件的拓展名
*.gz gzip程序压缩的文件
*.bz2 bzip程序压缩的文件
*.tar tar程序打包的数据,没有经过压缩
*.tar.gz tar程序打包后,并经过gzip程序压缩
*.tar.bz2 tar程序打包后,并经过bzip程序压缩
*.zi
Android 应用程序发送shell命令
gqdy365
android
项目中需要直接在APP中通过发送shell指令来控制lcd灯,其实按理说应该是方案公司在调好lcd灯驱动之后直接通过service送接口上来给APP,APP调用就可以控制了,这是正规流程,但我们项目的方案商用的mtk方案,方案公司又没人会改,只调好了驱动,让应用程序自己实现灯的控制,这不蛋疼嘛!!!!
发就发吧!
一、关于shell指令:
我们知道,shell指令是Linux里面带的
java 无损读取文本文件
hw1287789687
读取文件 无损读取 读取文本文件 charset
java 如何无损读取文本文件呢?
以下是有损的
@Deprecated
public static String getFullContent(File file, String charset) {
BufferedReader reader = null;
if (!file.exists()) {
System.out.println("getFull
Firebase 相关文章索引
justjavac
firebase
Awesome Firebase
最近谷歌收购Firebase的新闻又将Firebase拉入了人们的视野,于是我做了这个 github 项目。
Firebase 是一个数据同步的云服务,不同于 Dropbox 的「文件」,Firebase 同步的是「数据」,服务对象是网站开发者,帮助他们开发具有「实时」(Real-Time)特性的应用。
开发者只需引用一个 API 库文件就可以使用标准 RE
C++学习重点
lx.asymmetric
C++ 笔记
1.c++面向对象的三个特性:封装性,继承性以及多态性。
2.标识符的命名规则:由字母和下划线开头,同时由字母、数字或下划线组成;不能与系统关键字重名。
3.c++语言常量包括整型常量、浮点型常量、布尔常量、字符型常量和字符串性常量。
4.运算符按其功能开以分为六类:算术运算符、位运算符、关系运算符、逻辑运算符、赋值运算符和条件运算符。
&n
java bean和xml相互转换
q821424508
java bean xml xml和bean转换 java bean和xml转换
这几天在做微信公众号
做的过程中想找个java bean转xml的工具,找了几个用着不知道是配置不好还是怎么回事,都会有一些问题,
然后脑子一热谢了一个javabean和xml的转换的工具里,自己用着还行,虽然有一些约束吧 ,
还是贴出来记录一下
顺便你提一下下,这个转换工具支持属性为集合、数组和非基本属性的对象。
packag
C 语言初级 位运算
1140566087
位运算 c
第十章 位运算 1、位运算对象只能是整形或字符型数据,在VC6.0中int型数据占4个字节 2、位运算符: 运算符 作用 ~ 按位求反 << 左移 >> 右移 & 按位与 ^ 按位异或 | 按位或 他们的优先级从高到低; 3、位运算符的运算功能: a、按位取反: ~01001101 = 101
14点睛Spring4.1-脚本编程
wiselyman
spring4
14.1 Scripting脚本编程
脚本语言和java这类静态的语言的主要区别是:脚本语言无需编译,源码直接可运行;
如果我们经常需要修改的某些代码,每一次我们至少要进行编译,打包,重新部署的操作,步骤相当麻烦;
如果我们的应用不允许重启,这在现实的情况中也是很常见的;
在spring中使用脚本编程给上述的应用场景提供了解决方案,即动态加载bean;
spring支持脚本