referrer相关知识
-
Web 页面 Meta 的 Referrer Policy一个图片,本站或者外站,都要想办法拿到前言介绍近期在一个项目中,需要引用大量外部网站的图片,竟意外的发现在生成环境中没有问题,但在本地的开发环境下,有部分图片无法显示。于是就开启了跨域图片显示的斗争中。名词解释什么是引用策略(Referrer Policy)?引用策略就是从一个文档发出请求时,是否在请求头部定义 Referrer 的设置。目前很多网站的防盗链机制都是用头部定义 Referrer 来判断是否是盗链。其实这个很容易破解,自己在请求时加上 Referrer 头部就行。在哪些情况下会设置引用头呢?一般来说,加载一个 HTML 页面之后,本 HTML 页面里的 JavaScript 文件,CSS 文件,画面文件都会设置 Referrer。然后,点击这个 HTML 页面里的链接,跳转其它画面时,也会设置 Referrer。Referrer Policy 的值空字符串no-referrerno-referrer-when-downgradesame-originoriginstrict-originori
-
meta referrer与页面内video标签referrer近在做一个播放抖音视频的网页中遇到一个问题,抖音视频的url直接在浏览器中打开是没有问题的,直接打开本地的.html文件也是可以正常播放视频的,但访问服务器上的请求过来的页面就无法播放视频,浏览器里按F12查看network发现video标签里的src请求视频资源时报403 Forbiddn 错误。直接访问链接的请求头:正确的请求头出错的请求头:错误的请求头经过对比发现错误的请求头中多了个Referer字段,估计请求的是服务器 referer 做了判断,不是正常的referer就拒绝了,可以模拟他们的 referer 请求试下,测试发现, 通过 https 站点打开的页面, 可以正常打开视频链接,在 https 下, 发送的请求是不会带有 Referer 的header 的, 这个时候是可以正常加载视频的. 所以, 我们在 页面的 head 标签内, 增加一行代码,指定浏览器任何情况下都不发送Referer,这样就可以正常加载资源了。<meta name="referrer&quo
-
利用本地存储实现注册来源统计工作中遇到的需求是这样的 尽可能获取网站注册用户来源,如来自百度搜索,或者其他外链。 实现方式有很多,我们公司采用的是服务器端技术来实现的,我根据这个需求用前端技术实现了下。具体思路如下图所示 存储访问来源:通过referrer获取访问来源url,通过sessionStorage.setItem存储。 获取访问来源:通过sessionStorage.getItem获取。 具体实现细节看代码示例注释 代码示例: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>获取网站注册用户来源</ti
-
python 字符集基础知识字符 字符是一个信息单位,它是各种文字和符号的总称 字符集 字符集是字符的集合 ASCII 有128个字符 Unicode 包含了世界各国语言中的所有字符 字符编码 将字符集中的字符编码为特定的二进制数 ASCII 包含英文字母 数字 一些普通符号 用一个字节表示 Unicode 它为每种语言的每个字符设定了独一无二的编码 utf-8 utf-8 是一种可变长的字符编码 用一到四个字节来表示字符 英文使用一个字节编码 汉字使用三个字节进行编码 python3 的默认编码是 utf-8 import sys sys.get
referrer相关课程
referrer相关教程
- 4.1 requests 模块 requests 是一个的简单易用的 http 库,发出 http 请求并获取响应,可以用于抓取网站的页面。使用 requests.get(url) 方法抓取 baidu 的首页,示例如下:>>> import requests>>> response = requests.get('https://www.baidu.com')>>> response.text'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer>...在第 2 行,使用 requests.get(‘https://www.baidu.com’) 获取 baidu 首页在第 3 行,response.text 是 baidu 首页 html 文件的内容
- 2.1 图片的行内定义 在 Markdown 文件中,使用 ![替换文字](图片路径 "标题(可选)") 的形式定义图片实例 1:#### 插入一张图片图片前的文字。![](https://tva3.sinaimg.cn/crop.0.0.180.180.180/6d04a77djw1e8qgp5bmzyj2050050aa8.jpg?KID=imgbed,tva&Expires=1588529780&ssig=vNCcwnltm2)图片后的文字渲染结果如下:图片来源于网络,版权归原作者所有该源码渲染输出 html 的内容如下:<h4>插入一张图片</h4><p>图片前的文字。</p><p><img src="https://c-ssl.duitang.com/uploads/item/201905/03/20190503105835_VfkU3.thumb.1000_0.png" referrerpolicy="no-referrer"></p><p>图片后的文字。</p>
- 1. Requests 库的使用 通常对于 Python 第三方模块的学习方式都是一样的。第一步都是先安装,然后是不断的使用和参考官方文档,待熟练掌握后便可以翻看其源码深入学习其实现原理,最后达到彻底掌握该模块的地步。[store@server2 chap02]$ pip3 install requests -i http://pypi.douban.com/simple/接下来我们参考官方文档的第一个实例进行测试,该实例主要是测试 requests 库的一些方法及其使用场景,后面我们会使用 requests 库对网页的数据进行手工爬取以比较和框架爬虫之间的区别。后续都将会在 CentOS7.8 和 Python 3 的环境下:[store@server2 chap02]$ python3Python 3.6.8 (default, Apr 2 2020, 13:34:55) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linuxType "help", "copyright", "credits" or "license" for more information.>>> import requests>>>Scrapy 百度百科接下来我们使用 requests 模块的 get() 方法模拟 http 的 get 请求,获取这样的页面结果:>>> headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'}>>> r1 = requests.get(url='https://baike.baidu.com/item/scrapy', headers=headers)>>> r1.status_code200>>> r1.text[:1000]'<!DOCTYPE html>\n<!--STATUS OK-->\n<html>\n\n\n\n<head>\n<meta charset="UTF-8">\n<meta http-equiv="X-UA-Compatible" content="IE=Edge" />\n<meta name="referrer" content="always" />\n<meta name="description" content="Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持。...">\n<title>scrapy_百度百科</title>\n<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />\n<link rel="icon" sizes="any" mask href="//www.baidu.com/img/baidu.svg">\n\n<meta name="keywords" content="scrapy scrapy基本功能 scrapyScrapy架构 scrapy如何开始">\n<meta name="image" content="https://bkssl.bdimg.com/cms/static/baike.png">\n<meta name="csrf-token" content="">\n<meta itemprop="dateUpdate" content="2020-03-19 08:23:19" />\n\n<!--[if lte IE 9]>\n<script>\r\n (function() {\r\n var e = "abbr,article,aside,audio,canvas,datalist,details,dialog,eventsource,figure,footer,header,hgroup,mark,menu,meter,nav,outpu注意:这里 headers 非常重要,很多网站第一步会检查 headers,如果请求头中没有 User-Agent 就会直接判定为爬虫并采取相应措施进行限制。如下是没有加上 headers 的请求结果:没有 headers 的结果看到了么,简简单单的 get() 方法就能模拟 HTTP 的 get 请求,那么是不是还有 post()、put()、delete() 这些方法呢?答案是肯定的。
- 1.2 带参数的 get 请求 我们再来看看 get 请求带参数的方式,示例代码如下:>>> payload = {'key1': 'value1', 'key2': 'value2'}>>> r = requests.get('https://httpbin.org/get', params=payload)>>> r.url'https://httpbin.org/get?key1=value1&key2=value2'可以看到 get 请求所携带的参数就是在 url 后使用 ? 将参数的 key 和 value 组合起来,形成完整的请求 url。下面是 get 请求带参数的另一个例子,这里参数 key2 的值是一个列表。>>> payload = {'key1': 'value1', 'key2': ['value2', 'value3']}>>> r = requests.get('https://httpbin.org/get', params=payload)>>> r.url'https://httpbin.org/get?key1=value1&key2=value2&key2=value3'来看看 request 库请求的结果:>>> type(r)<class 'requests.models.Response'>>>> dir(r)['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_content', '_content_consumed', '_next', 'apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'next', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']这里用的最多的有5个,分别为 enconding、status_code、text、content 和 url,它们的含义如下:encoding:当读取 r.text 时会使用该值进行编解码;status_code:请求返回状态码,200 表示正常;text:返回请求的内容,使用 unicode 编码;content:返回请求的内容,字节编码;url:最终请求的 url。此外,对于所有的请求,可以带上 headers 参数,这样可以模拟成浏览器的行为。通常不带 headers 很容易就被识别为爬虫程序,通过百度网站的 get 请求就可以看到。带上正常的 header 和 不带或者带上错误的 header 得到的结果不一样:>>> url = 'https://www.baidu.com'>>> headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'}>>> r = requests.get(url, headers=headers)>>> r.text[:1000]'<!DOCTYPE html><!--STATUS OK-->\n\n\n <html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta content="always" name="referrer"><meta name="theme-color" content="#2932e1"><meta name="description" content="全球最大的中文搜索引擎、致力于让网民更便捷地获取信息,找到所求。百度超过千亿的中文网页数据库,可以瞬间找到相关的搜索结果。"><link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /><link rel="search" type="application/opensearchdescription+xml" href="/content-search.xml" title="百度搜索" /><link rel="icon" sizes="any" mask href="//www.baidu.com/img/baidu_85beaf5496f291521eb75ba38eacbd87.svg"><link rel="dns-prefetch" href="//dss0.bdstatic.com"/><link rel="dns-prefetch" href="//dss1.bdstatic.com"/><link rel="dns-prefetch" href="//ss1.bdstatic.com"/><link rel="dns-prefetch" href="//sp0.baidu.com"/><link rel="dns-prefetch" href="//sp1.baidu.com"/><link rel="dns-prefetch" href="//sp2.baidu.com"/><title>百度一下,你就知道</title><style index="newi" type="text/css">>>> headers = {'user-agent': 'my-app/0.0.1'}>>> r = requests.get(url, headers=headers)>>> r.text'<html>\r\n<head>\r\n\t<script>\r\n\t\tlocation.replace(location.href.replace("https://","http://"));\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>\r\n</body>\r\n</html>'前面我们也介绍过 requests 库的 post 请求,其参数通过 data 进行传递,下面继续看几个示例:>>> payload_tuples = [('key1', 'value1'), ('key1', 'value2')]>>> r1 = requests.post('https://httpbin.org/post', data=payload_tuples)>>> payload_dict = {'key1': ['value1', 'value2']}>>> r2 = requests.post('https://httpbin.org/post', data=payload_dict)>>> print(r1.text){ "args": {}, "data": "", "files": {}, "form": { "key1": [ "value1", "value2" ] }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "23", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.24.0", "X-Amzn-Trace-Id": "Root=1-5ef49697-c3f6e2a809e33d4895ee6938" }, "json": null, "origin": "47.115.61.209", "url": "https://httpbin.org/post"}
- 2. Respone 类 Response 类主要是封装了前面请求的响应结果,爬虫的一个很重要的部分就是解析这些 Response,得到我们想要的结果。这一部分内容我们就来深入分析 Response 类以及扩展类。Response类相关代码翻看源码,我们可以得到如下信息:__init__.py 中定义了 Response 基类;text.pym 中定义的 TextResponse 类直接继承 Response 类并进行了一系列扩展和重载部分方法;html.py 和 xml.py 中分别定义的 HtmlResponse 和 XmlResponse 都只继承了 TextResponse ,并未做过多的修改,只是分别取了个别名:# 源码位置:scrapy/http/response/html.pyfrom scrapy.http.response.text import TextResponseclass HtmlResponse(TextResponse): pass# 源码位置:scrapy/http/response/xml.pyfrom scrapy.http.response.text import TextResponseclass XmlResponse(TextResponse): pass接下来我们的重点就是学习 Response 类和 TextResponse 类。Response 类有如下几个常用属性值:headers:头部信息;status:返回状态码;body:响应内容;url:请求的 url;request:对应的 request 请求;ip_address:请求的 ip 地址。我们还是通过 Scrapy Shell 请求广州链家二手房的地址来看看真实的 Response 并打印上述值:(scrapy-test) [root@server ~]# scrapy shell https://gz.lianjia.com/ershoufang/ --nolog[s] Available Scrapy objects:[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)[s] crawler <scrapy.crawler.Crawler object at 0x7f9890d5a100>[s] item {}[s] request <GET https://gz.lianjia.com/ershoufang/>[s] response <200 https://gz.lianjia.com/ershoufang/>[s] settings <scrapy.settings.Settings object at 0x7f9890d57bb0>[s] spider <DefaultSpider 'default' at 0x7f989034dd90>[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>>> response.headers{b'Server': [b'Lianjia'], b'Date': [b'Sun, 12 Jul 2020 07:37:16 GMT'], b'Content-Type': [b'text/html; charset=UTF-8'], b'Vary': [b'Accept-Encoding'], b'Set-Cookie': [b'select_city=440100; expires=Mon, 13-Jul-2020 07:37:16 GMT; Max-Age=86400; path=/; domain=.lianjia.com', b'lianjia_ssid=a0980b19-93f6-4942-a898-96ea722d524d; expires=Sun, 12-Jul-20 08:07:16 GMT; Max-Age=1800; domain=.lianjia.com; path=/', b'lianjia_uuid=12165c9c-6c66-4996-9e2c-623a838efd4a; expires=Wed, 10-Jul-30 07:37:16 GMT; Max-Age=315360000; domain=.lianjia.com; path=/'], b'Via': [b'web05-online.zeus.ljnode.com']}>>> response.status200>>> response.url'https://gz.lianjia.com/ershoufang/'>>> response.ip_addressIPv4Address('211.159.232.241')>>> >>> response.request<GET https://gz.lianjia.com/ershoufang/>>>> 注意:关于这个 response,我们前面在分析 scrapy shell [url] 命令的执行过程中说过,如果命令后面带上要爬取的 URL 地址,那么在交互式的 shell 生成前,会将一些得到的基本的环境变量包括请求 URL 的响应结果 (response) 放到该环境变量中,这就是为什么我们能在该交互模式下直接使用 response 获取请求结果的原因。来看看 Response 类中预留的一些方法:# 源码位置:scrapy/http/response/__init__.py# ...class Response(object_ref): def __init__(self, url, status=200, headers=None, body=b'', flags=None, request=None, certificate=None, ip_address=None): self.headers = Headers(headers or {}) self.status = int(status) self._set_body(body) self._set_url(url) self.request = request self.flags = [] if flags is None else list(flags) self.certificate = certificate self.ip_address = ip_address # ... @property def text(self): """For subclasses of TextResponse, this will return the body as str """ raise AttributeError("Response content isn't text") def css(self, *a, **kw): """Shortcut method implemented only by responses whose content is text (subclasses of TextResponse). """ raise NotSupported("Response content isn't text") def xpath(self, *a, **kw): """Shortcut method implemented only by responses whose content is text (subclasses of TextResponse). """ raise NotSupported("Response content isn't text") # ...上面这些预留的 text 属性、css() 方法以及 xpath() 方法都会在 TextResponse 中有相应的实现。接下来我们仔细分析 TextResponse 的这些属性和的方法:# 源码位置: class TextResponse(Response): _DEFAULT_ENCODING = 'ascii' _cached_decoded_json = _NONE def __init__(self, *args, **kwargs): self._encoding = kwargs.pop('encoding', None) self._cached_benc = None self._cached_ubody = None self._cached_selector = None super(TextResponse, self).__init__(*args, **kwargs) # ...从 __init__() 方法中可以看到,TextResponse 的属性和父类基本没变化,只是增加了一些用于缓存的属性。接下来我们再看几个重要的属性和方法:# ...class TextResponse(Response): .... @property def text(self): """ Body as unicode """ # access self.encoding before _cached_ubody to make sure # _body_inferred_encoding is called benc = self.encoding if self._cached_ubody is None: charset = 'charset=%s' % benc self._cached_ubody = html_to_unicode(charset, self.body)[1] return self._cached_ubody # ...上面这段代码的逻辑就是将 body 属性中的值转成 str,我们可以在 Scrapy Shell 模式下复现这一操作:(scrapy-test) [root@server ~]# scrapy shell https://www.baidu.com --nolog[s] Available Scrapy objects:[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)[s] crawler <scrapy.crawler.Crawler object at 0x7faf4f318190>[s] item {}[s] request <GET https://www.baidu.com>[s] response <200 https://www.baidu.com>[s] settings <scrapy.settings.Settings object at 0x7faf4f315b50>[s] spider <DefaultSpider 'default' at 0x7faf4e9122b0>[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>>> response.bodyb'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b\xef\xbc\x8c\xe4\xbd\xa0\xe5\xb0\xb1\xe7\x9f\xa5\xe9\x81\x93</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>\xe6\x96\xb0\xe9\x97\xbb</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>\xe5\x9c\xb0\xe5\x9b\xbe</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>\xe8\xa7\x86\xe9\xa2\x91</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>\xe8\xb4\xb4\xe5\x90\xa7</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>\xe7\x99\xbb\xe5\xbd\x95</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">\xe7\x99\xbb\xe5\xbd\x95</a>\');\r\n </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">\xe6\x9b\xb4\xe5\xa4\x9a\xe4\xba\xa7\xe5\x93\x81</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>\xe5\x85\xb3\xe4\xba\x8e\xe7\x99\xbe\xe5\xba\xa6</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>\xe4\xbd\xbf\xe7\x94\xa8\xe7\x99\xbe\xe5\xba\xa6\xe5\x89\x8d\xe5\xbf\x85\xe8\xaf\xbb</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>\xe6\x84\x8f\xe8\xa7\x81\xe5\x8f\x8d\xe9\xa6\x88</a> \xe4\xba\xacICP\xe8\xaf\x81030173\xe5\x8f\xb7 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>\r\n'>>> type(response.body)<class 'bytes'>>>> from w3lib.encoding import html_to_unicode>>> html_to_unicode("charset=None", response.body)('utf-8', '<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">登录</a>\');\r\n </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>\r\n')可以看到 ,Response 中的 body 属性值是 bytes 类型,通过 html_to_unicode() 方法可以将其转成 str,然后我们得到的网页文本就是 str 类型:>>> text = html_to_unicode("charset=None", response.body)>>> type(text[1])<class 'str'>接下来的这三个方法我们在上一节介绍过,正是由于有了这些属性和方法,我们便可以使用 response.xpath() 或者 response.css() 这样的写法提取网页数据。# ...class TextResponse(Response): .... @property def selector(self): from scrapy.selector import Selector if self._cached_selector is None: self._cached_selector = Selector(self) return self._cached_selector def xpath(self, query, **kwargs): return self.selector.xpath(query, **kwargs) def css(self, query): return self.selector.css(query)TextResponse 类比较重要的属性和方法就这些,其他的则需要自行深入去研究相关的方法及其作用。我们现在来解答上一节提出的问题:为什么 Scrapy 的 TextResponse 实例可以使用这样的表达式:response.xpath(...).extrat()[0] 或者 response.xpath(...).extrat_first()?接下来我们带着这个问题来继续追踪下代码。我们以上一节的例子为例,打印 response.xpath() 的返回类型:(scrapy-test) [root@server ~]# scrapy shell https://gz.lianjia.com/ershoufang/ --nolog...>>> data = response.xpath('//ul[@class="sellListContent"]/li/div/div[@class="title"]/a/text()')>>> type(data)<class 'scrapy.selector.unified.SelectorList'>>>> 可以看到结果是 SelectorList 实例,我们来看对应定义的代码:# 源码位置:scrapy/selector/unified.pyfrom parsel import Selector as _ParselSelector# ...class SelectorList(_ParselSelector.selectorlist_cls, object_ref): """ The :class:`SelectorList` class is a subclass of the builtin ``list`` class, which provides a few additional methods. """它直接继承的是 parsel 模块中的 selectorlist_cls。继续看这个值的定义:# 源码位置:parsel/selector.pyclass Selector(object): # ... selectorlist_cls = SelectorList # ...# 源码位置:parsel/selector.pyclass SelectorList(list): # ... def getall(self): """ Call the ``.get()`` method for each element is this list and return their results flattened, as a list of unicode strings. """ return [x.get() for x in self] extract = getall def get(self, default=None): """ Return the result of ``.get()`` for the first element in this list. If the list is empty, return the default value. """ for x in self: return x.get() return default extract_first = get是不是找到了 extract() 和 extract_first() 方法?注意理解这段代码:for x in self: return x.get()return defaultself 表示的是 SelectorList 的实例,它其实也是一个列表,列表中的元素是 Selector 的实例。这个 for 循环相当于取的是一个元素,然后直接返回,返回的值是 x.get(),这里又会涉及 Selector 类的 get() 方法 :# 源码位置:parsel/selector.pyfrom lxml import etree, html# ...class Selector(object): # ... def get(self): """ Serialize and return the matched nodes in a single unicode string. Percent encoded content is unquoted. """ try: return etree.tostring(self.root, method=self._tostring_method, encoding='unicode', with_tail=False) except (AttributeError, TypeError): if self.root is True: return u'1' elif self.root is False: return u'0' else: return six.text_type(self.root) # ...我们可以同样在 Scrapy Shell 中来继续做个测试:>>> data_list = response.xpath('//ul[@class="sellListContent"]/li/div/div[@class="title"]/a/text()')>>> type(data_list)<class 'scrapy.selector.unified.SelectorList'>>>> data = data_list[0]>>> type(data)<class 'scrapy.selector.unified.Selector'>>>> data.get()'地铁口 总价低 精装实用小两房'Selector 的 get() 方法最后提取出了我们匹配的文本,因此在 SelectorList 中的 extract()[0] 和 ``extract_first()` 方法将得到同样的结果:>>> response.xpath('//ul[@class="sellListContent"]/li/div/div[@class="title"]/a/text()').extract_first()'地铁口 总价低 精装实用小两房'>>> response.xpath('//ul[@class="sellListContent"]/li/div/div[@class="title"]/a/text()').extract()[0]'地铁口 总价低 精装实用小两房'这样一步步追踪和实验,源码里面很多的语句就会清晰明了,我们在使用 Request 和 Response 类时便会显得更加得心应手。Request 实例化时需要哪些参数,Response 的实例有哪些方法可用, 这些疑惑在源码面前都会迎刃而解。
- 同步器(中)——AbstractQueuedSy 笑傲Java面试 面霸修炼手册
referrer相关搜索
-
radio
radiobutton
radiobuttonlist
radiogroup
radio选中
radius
rails
raise
rand
random_shuffle
randomflip
random函数
rangevalidator
rarlinux
ratio
razor
react
react native
react native android
react native 中文