精华内容
下载资源
问答
  • 手把手教你利用爬虫爬网页(Python代码)

    万次阅读 多人点赞 2019-05-14 14:34:48
    但是有时候会遇到这种情况,我们不想让urllib2自动处理,我们想自己添加Cookie的内容,可以通过设置请求头中的Cookie域来: import  urllib2 opener = urllib2.build_opener() opener.addheaders.append( (  ...

    640?wx_fmt=jpeg

    本文主要分为两个部分:一部分是网络爬虫的概述,帮助大家详细了解网络爬虫;另一部分是HTTP请求的Python实现,帮助大家了解Python中实现HTTP请求的各种方式,以便具备编写HTTP网络程序的能力。


    01

    网络爬虫概述


    接下来从网络爬虫的概念、用处与价值和结构等三个方面,让大家对网络爬虫有一个基本的了解。

    1. 网络爬虫及其应用

    随着网络的迅速发展,万维网成为大量信息的载体,如何有效地提取并利用这些信息成为一个巨大的挑战,网络爬虫应运而生。网络爬虫(又被称为网页蜘蛛、网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。下面通过图3-1展示一下网络爬虫在互联网中起到的作用:


    640?wx_fmt=png

    ▲图3-1 网络爬虫


    网络爬虫按照系统结构和实现技术,大致可以分为以下几种类型:通用网络爬虫、聚焦网络爬虫、增量式网络爬虫、深层网络爬虫。实际的网络爬虫系统通常是几种爬虫技术相结合实现的。

    搜索引擎(Search Engine),例如传统的通用搜索引擎baidu、Yahoo和Google等,是一种大型复杂的网络爬虫,属于通用性网络爬虫的范畴。但是通用性搜索引擎存在着一定的局限性:

    1. 不同领域、不同背景的用户往往具有不同的检索目的和需求,通用搜索引擎所返回的结果包含大量用户不关心的网页。

    2. 通用搜索引擎的目标是尽可能大的网络覆盖率,有限的搜索引擎服务器资源与无限的网络数据资源之间的矛盾将进一步加深。

    3. 万维网数据形式的丰富和网络技术的不断发展,图片、数据库、音频、视频多媒体等不同数据大量出现,通用搜索引擎往往对这些信息含量密集且具有一定结构的数据无能为力,不能很好地发现和获取。

    4. 通用搜索引擎大多提供基于关键字的检索,难以支持根据语义信息提出的查询。

    为了解决上述问题,定向抓取相关网页资源的聚焦爬虫应运而生。

    聚焦爬虫是一个自动下载网页的程序,它根据既定的抓取目标,有选择地访问万维网上的网页与相关的链接,获取所需要的信息。与通用爬虫不同,聚焦爬虫并不追求大的覆盖,而将目标定为抓取与某一特定主题内容相关的网页,为面向主题的用户查询准备数据资源。

    说完了聚焦爬虫,接下来再说一下增量式网络爬虫。增量式网络爬虫是指对已下载网页采取增量式更新和只爬行新产生的或者已经发生变化网页的爬虫,它能够在一定程度上保证所爬行的页面是尽可能新的页面。

    和周期性爬行和刷新页面的网络爬虫相比,增量式爬虫只会在需要的时候爬行新产生或发生更新的页面,并不重新下载没有发生变化的页面,可有效减少数据下载量,及时更新已爬行的网页,减小时间和空间上的耗费,但是增加了爬行算法的复杂度和实现难度。

    例如:想获取赶集网的招聘信息,以前爬取过的数据没有必要重复爬取,只需要获取更新的招聘数据,这时候就要用到增量式爬虫。

    最后说一下深层网络爬虫。Web页面按存在方式可以分为表层网页和深层网页。表层网页是指传统搜索引擎可以索引的页面,以超链接可以到达的静态网页为主构成的Web页面。深层网络是那些大部分内容不能通过静态链接获取的、隐藏在搜索表单后的,只有用户提交一些关键词才能获得的Web页面。

    例如用户登录或者注册才能访问的页面。可以想象这样一个场景:爬取贴吧或者论坛中的数据,必须在用户登录后,有权限的情况下才能获取完整的数据。

    2. 网络爬虫结构

    下面用一个通用的网络爬虫结构来说明网络爬虫的基本工作流程,如图3-4所示。


    640?wx_fmt=png

    ▲图3-4 网络爬虫结构

    网络爬虫的基本工作流程如下:

    1. 首先选取一部分精心挑选的种子URL。

    2. 将这些URL放入待抓取URL队列。

    3. 从待抓取URL队列中读取待抓取队列的URL,解析DNS,并且得到主机的IP,并将URL对应的网页下载下来,存储进已下载网页库中。此外,将这些URL放进已抓取URL队列。

    4. 分析已抓取URL队列中的URL,从已下载的网页数据中分析出其他URL,并和已抓取的URL进行比较去重,最后将去重过的URL放入待抓取URL队列,从而进入下一个循环。

    02

    HTTP请求的Python实现


    通过上面的网络爬虫结构,我们可以看到读取URL、下载网页是每一个爬虫必备而且关键的功能,这就需要和HTTP请求打交道。接下来讲解Python中实现HTTP请求的三种方式:urllib2/urllib、httplib/urllib以及Requests。

    1. urllib2/urllib实现

    urllib2和urllib是Python中的两个内置模块,要实现HTTP功能,实现方式是以urllib2为主,urllib为辅。

    1.1 首先实现一个完整的请求与响应模型

    urllib2提供一个基础函数urlopen,通过向指定的URL发出请求来获取数据。最简单的形式是:

    
     

    import urllib2
    response=urllib2.urlopen('http://www.zhihu.com')
    html=response.read()
    print html

    其实可以将上面对http://www.zhihu.com的请求响应分为两步,一步是请求,一步是响应,形式如下:

    
     

    import urllib2
    # 请求
    request=urllib2.Request('http://www.zhihu.com')
    # 响应
    response = urllib2.urlopen(request)
    html=response.read()
    print html

    上面这两种形式都是GET请求,接下来演示一下POST请求,其实大同小异,只是增加了请求数据,这时候用到了urllib。示例如下:

    
     

    import urllib
    import urllib2
    url = 'http://www.xxxxxx.com/login'
    postdata = {'username' : 'qiye',
        'password' : 'qiye_pass'}
    # info 需要被编码为urllib2能理解的格式,这里用到的是urllib
    data = urllib.urlencode(postdata)
    req = urllib2.Request(url, data)
    response = urllib2.urlopen(req)
    html = response.read()

    但是有时会出现这种情况:即使POST请求的数据是对的,但是服务器拒绝你的访问。这是为什么呢?问题出在请求中的头信息,服务器会检验请求头,来判断是否是来自浏览器的访问,这也是反爬虫的常用手段。

    1.2 请求头headers处理

    将上面的例子改写一下,加上请求头信息,设置一下请求头中的User-Agent域和Referer域信息。

    
     

    import urllib
    import urllib2
    url = 'http://www.xxxxxx.com/login'
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    referer='http://www.xxxxxx.com/'
    postdata = {'username' : 'qiye',
        'password' : 'qiye_pass'}
    # 将user_agent,referer写入头信息
    headers={'User-Agent':user_agent,'Referer':referer}
    data = urllib.urlencode(postdata)
    req = urllib2.Request(url, data,headers)
    response = urllib2.urlopen(req)
    html = response.read()

    也可以这样写,使用add_header来添加请求头信息,修改如下:

    
     

    import urllib
    import urllib2
    url = 'http://www.xxxxxx.com/login'
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    referer='http://www.xxxxxx.com/'
    postdata = {'username' : 'qiye',
        'password' : 'qiye_pass'}
    data = urllib.urlencode(postdata)
    req = urllib2.Request(url)
    # 将user_agent,referer写入头信息
    req.add_header('User-Agent',user_agent)
    req.add_header('Referer',referer)
    req.add_data(data)
    response = urllib2.urlopen(req)
    html = response.read()

    对有些header要特别留意,服务器会针对这些header做检查,例如:

    • User-Agent:有些服务器或Proxy会通过该值来判断是否是浏览器发出的请求。

    • Content-Type:在使用REST接口时,服务器会检查该值,用来确定HTTP Body中的内容该怎样解析。在使用服务器提供的RESTful或SOAP服务时,Content-Type设置错误会导致服务器拒绝服务。常见的取值有:application/xml(在XML RPC,如RESTful/SOAP调用时使用)、application/json(在JSON RPC调用时使用)、application/x-www-form-urlencoded(浏览器提交Web表单时使用)。

    • Referer:服务器有时候会检查防盗链。

    1.3 Cookie处理

    urllib2对Cookie的处理也是自动的,使用CookieJar函数进行Cookie的管理。如果需要得到某个Cookie项的值,可以这么做:

    
     

    import urllib2
    import cookielib
    cookie = cookielib.CookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
    response = opener.open('http://www.zhihu.com')
    for item in cookie:
        print item.name+':'+item.value

    但是有时候会遇到这种情况,我们不想让urllib2自动处理,我们想自己添加Cookie的内容,可以通过设置请求头中的Cookie域来做:

    
     

    import  urllib2
    opener = urllib2.build_opener()
    opener.addheaders.append( ( 'Cookie''email=' + "xxxxxxx@163.com" ) )
    req = urllib2.Request( "http://www.zhihu.com/" )
    response = opener.open(req)
    print response.headers
    retdata = response.read()

    1.4 Timeout设置超时

    在Python2.6之前的版本,urllib2的API并没有暴露Timeout的设置,要设置Timeout值,只能更改Socket的全局Timeout值。示例如下:

    
     

    import urllib2
    import socket
    socket.setdefaulttimeout(10# 10 秒钟后超时
    urllib2.socket.setdefaulttimeout(10# 另一种方式

    在Python2.6及新的版本中,urlopen函数提供了对Timeout的设置,示例如下:

    
     

    import urllib2
    request=urllib2.Request('http://www.zhihu.com')
    response = urllib2.urlopen(request,timeout=2)
    html=response.read()
    print html

    1.5 获取HTTP响应码

    对于200 OK来说,只要使用urlopen返回的response对象的getcode()方法就可以得到HTTP的返回码。但对其他返回码来说,urlopen会抛出异常。这时候,就要检查异常对象的code属性了,示例如下:

    
     

    import urllib2
    try:
        response = urllib2.urlopen('http://www.google.com')
        print response
    except urllib2.HTTPError as e:
        if hasattr(e, 'code'):
            print 'Error code:',e.code

    1.6 重定向

    urllib2默认情况下会针对HTTP 3XX返回码自动进行重定向动作。要检测是否发生了重定向动作,只要检查一下Response的URL和Request的URL是否一致就可以了,示例如下:

    
     

    import urllib2
    response = urllib2.urlopen('http://www.zhihu.cn')
    isRedirected = response.geturl() == 'http://www.zhihu.cn'

    如果不想自动重定向,可以自定义HTTPRedirectHandler类,示例如下:

    
     

    import urllib2
    class RedirectHandler(urllib2.HTTPRedirectHandler):
        def http_error_301(self, req, fp, code, msg, headers):
            pass
        def http_error_302(self, req, fp, code, msg, headers):
            result = urllib2.HTTPRedirectHandler.http_error_301(self, req, fp, code, 
            msg, headers)
            result.status = code
            result.newurl = result.geturl()
            return result
    opener = urllib2.build_opener(RedirectHandler)
    opener.open('http://www.zhihu.cn')

    1.7 Proxy的设置

    在做爬虫开发中,必不可少地会用到代理。urllib2默认会使用环境变量http_proxy来设置HTTP Proxy。但是我们一般不采用这种方式,而是使用ProxyHandler在程序中动态设置代理,示例代码如下:

    
     

    import urllib2
    proxy = urllib2.ProxyHandler({'http''127.0.0.1:8087'})
    opener = urllib2.build_opener([proxy,])
    urllib2.install_opener(opener)
    response = urllib2.urlopen('http://www.zhihu.com/')
    print response.read()

    这里要注意的一个细节,使用urllib2.install_opener()会设置urllib2的全局opener,之后所有的HTTP访问都会使用这个代理。这样使用会很方便,但不能做更细粒度的控制,比如想在程序中使用两个不同的Proxy设置,这种场景在爬虫中很常见。比较好的做法是不使用install_opener去更改全局的设置,而只是直接调用opener的open方法代替全局的urlopen方法,修改如下:

    
     

    import urllib2
    proxy = urllib2.ProxyHandler({'http''127.0.0.1:8087'})
    opener = urllib2.build_opener(proxy,)
    response = opener.open("http://www.zhihu.com/")
    print response.read()


    2. httplib/urllib实现

    httplib模块是一个底层基础模块,可以看到建立HTTP请求的每一步,但是实现的功能比较少,正常情况下比较少用到。在Python爬虫开发中基本上用不到,所以在此只是进行一下知识普及。下面介绍一下常用的对象和函数:


    • 创建HTTPConnection对象:

      class httplib.HTTPConnection(host[, port[, strict[, timeout[, source_address]]]])。

    • 发送请求:

      HTTPConnection.request(method, url[, body[, headers]])。

    • 获得响应:

      HTTPConnection.getresponse()。

    • 读取响应信息:

      HTTPResponse.read([amt])。

    • 获得指定头信息:

      HTTPResponse.getheader(name[, default])。

    • 获得响应头(header, value)元组的列表:

      HTTPResponse.getheaders()。

    • 获得底层socket文件描述符:

      HTTPResponse.fileno()。

    • 获得头内容:

      HTTPResponse.msg。

    • 获得头http版本:

      HTTPResponse.version。

    • 获得返回状态码:

      HTTPResponse.status。

    • 获得返回说明:

      HTTPResponse.reason。

    接下来演示一下GET请求和POST请求的发送,首先是GET请求的示例,如下所示:

    
     

    import httplib
    conn =None
    try:
        conn = httplib.HTTPConnection("www.zhihu.com")
        conn.request("GET""/")
        response = conn.getresponse()
        print response.status, response.reason
        print '-' * 40
        headers = response.getheaders()
        for h in headers:
            print h
        print '-' * 40
        print response.msg
    except Exception,e:
        print e
    finally:
        if conn:
            conn.close()

    POST请求的示例如下:

    
     

    import httplib, urllib
    conn = None
    try:
        params = urllib.urlencode({'name''qiye''age'22})
        headers = {"Content-type""application/x-www-form-urlencoded"
        , "Accept""text/plain"}
        conn = httplib.HTTPConnection("www.zhihu.com"80, timeout=3)
        conn.request("POST""/login", params, headers)
        response = conn.getresponse()
        print response.getheaders() # 获取头信息
        print response.status
        print response.read()
    except Exception, e:
        print e
        finally:
        if conn:
            conn.close()

    3. 更人性化的Requests

    Python中Requests实现HTTP请求的方式,是本人极力推荐的,也是在Python爬虫开发中最为常用的方式。Requests实现HTTP请求非常简单,操作更加人性化。

    Requests库是第三方模块,需要额外进行安装。Requests是一个开源库,源码位于:

    GitHub: https://github.com/kennethreitz/requests

    希望大家多多支持作者。

    使用Requests库需要先进行安装,一般有两种安装方式:

    • 使用pip进行安装,安装命令为:pip install requests,不过可能不是最新版。

    • 直接到GitHub上下载Requests的源代码,下载链接为:

      https://github.com/kennethreitz/requests/releases

      将源代码压缩包进行解压,然后进入解压后的文件夹,运行setup.py文件即可。

    如何验证Requests模块安装是否成功呢?在Python的shell中输入import requests,如果不报错,则是安装成功。如图3-5所示。

    640?wx_fmt=png

    ▲图3-5 验证Requests安装

    3.1 首先还是实现一个完整的请求与响应模型

    以GET请求为例,最简单的形式如下:

    
     

    import requests
    r = requests.get('http://www.baidu.com')
    print r.content

    大家可以看到比urllib2实现方式的代码量少。接下来演示一下POST请求,同样是非常简短,更加具有Python风格。示例如下:

    
     

    import requests
    postdata={'key':'value'}
    r = requests.post('http://www.xxxxxx.com/login',data=postdata)
    print r.content

    HTTP中的其他请求方式也可以用Requests来实现,示例如下:

    
     

    r = requests.put('http://www.xxxxxx.com/put', data = {'key':'value'})
    r = requests.delete('http://www.xxxxxx.com/delete')
    r = requests.head('http://www.xxxxxx.com/get')
    r = requests.options('http://www.xxxxxx.com/get')

    接着讲解一下稍微复杂的方式,大家肯定见过类似这样的URL:

    http://zzk.cnblogs.com/s/blogpost?Keywords=blog:qiyeboy&pageindex=1

    就是在网址后面紧跟着“?”,“?”后面还有参数。那么这样的GET请求该如何发送呢?肯定有人会说,直接将完整的URL带入即可,不过Requests还提供了其他方式,示例如下:

    
     

    import requests
        payload = {'Keywords''blog:qiyeboy','pageindex':1}
    r = requests.get('http://zzk.cnblogs.com/s/blogpost', params=payload)
    print r.url

    通过打印结果,我们看到最终的URL变成了:

    http://zzk.cnblogs.com/s/blogpost?Keywords=blog:qiyeboy&pageindex=1

    3.2 响应与编码

    还是从代码入手,示例如下:

    
     

    import requests
    r = requests.get('http://www.baidu.com')
    print 'content-->'+r.content
    print 'text-->'+r.text
    print 'encoding-->'+r.encoding
    r.encoding='utf-8'
    print 'new text-->'+r.text

    其中r.content返回的是字节形式,r.text返回的是文本形式,r.encoding返回的是根据HTTP头猜测的网页编码格式。

    输出结果中:“text-->”之后的内容在控制台看到的是乱码,“encoding-->”之后的内容是ISO-8859-1(实际上的编码格式是UTF-8),由于Requests猜测编码错误,导致解析文本出现了乱码。Requests提供了解决方案,可以自行设置编码格式,r.encoding='utf-8'设置成UTF-8之后,“new text-->”的内容就不会出现乱码。

    但是这种手动的方式略显笨拙,下面提供一种更加简便的方式:chardet,这是一个非常优秀的字符串/文件编码检测模块。安装方式如下:

    
     

    pip install chardet

    安装完成后,使用chardet.detect()返回字典,其中confidence是检测精确度,encoding是编码形式。示例如下:

    
     

    import requests
    r = requests.get('http://www.baidu.com')
    print chardet.detect(r.content)
    r.encoding = chardet.detect(r.content)['encoding']
    print r.text

    直接将chardet探测到的编码,赋给r.encoding实现解码,r.text输出就不会有乱码了。

    除了上面那种直接获取全部响应的方式,还有一种流模式,示例如下:

    
     

    import requests
    r = requests.get('http://www.baidu.com',stream=True)
    print r.raw.read(10)

    设置stream=True标志位,使响应以字节流方式进行读取,r.raw.read函数指定读取的字节数。

    3.3 请求头headers处理

    Requests对headers的处理和urllib2非常相似,在Requests的get函数中添加headers参数即可。示例如下:

    
     

    import requests
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers={'User-Agent':user_agent}
    r = requests.get('http://www.baidu.com',headers=headers)
    print r.content

    3.4 响应码code和响应头headers处理

    获取响应码是使用Requests中的status_code字段,获取响应头使用Requests中的headers字段。示例如下:

    
     

    import requests
    r = requests.get('http://www.baidu.com')
    if r.status_code == requests.codes.ok:
        print r.status_code# 响应码
        print r.headers# 响应头
        print r.headers.get('content-type')# 推荐使用这种获取方式,获取其中的某个字段
        print r.headers['content-type']# 不推荐使用这种获取方式
    else:
        r.raise_for_status()

    上述程序中,r.headers包含所有的响应头信息,可以通过get函数获取其中的某一个字段,也可以通过字典引用的方式获取字典值,但是不推荐,因为如果字段中没有这个字段,第二种方式会抛出异常,第一种方式会返回None。

    r.raise_for_status()是用来主动地产生一个异常,当响应码是4XX或5XX时,raise_for_status()函数会抛出异常,而响应码为200时,raise_for_status()函数返回None。

    3.5 Cookie处理

    如果响应中包含Cookie的值,可以如下方式获取Cookie字段的值,示例如下:

    
     

    import requests
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers={'User-Agent':user_agent}
    r = requests.get('http://www.baidu.com',headers=headers)
    # 遍历出所有的cookie字段的值
    for cookie in r.cookies.keys():
        print cookie+':'+r.cookies.get(cookie)

    如果想自定义Cookie值发送出去,可以使用以下方式,示例如下:

    
     

    import requests
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers={'User-Agent':user_agent}
    cookies = dict(name='qiye',age='10')
    r = requests.get('http://www.baidu.com',headers=headers,cookies=cookies)
    print r.text

    还有一种更加高级,且能自动处理Cookie的方式,有时候我们不需要关心Cookie值是多少,只是希望每次访问的时候,程序自动把Cookie的值带上,像浏览器一样。Requests提供了一个session的概念,在连续访问网页,处理登录跳转时特别方便,不需要关注具体细节。使用方法示例如下:

    
     

    import Requests
    oginUrl = 'http://www.xxxxxxx.com/login'
    s = requests.Session()
    #首先访问登录界面,作为游客,服务器会先分配一个cookie
    r = s.get(loginUrl,allow_redirects=True)
    datas={'name':'qiye','passwd':'qiye'}
    #向登录链接发送post请求,验证成功,游客权限转为会员权限
    r = s.post(loginUrl, data=datas,allow_redirects= True)
    print r.text

    上面的这段程序,其实是正式做Python开发中遇到的问题,如果没有第一步访问登录的页面,而是直接向登录链接发送Post请求,系统会把你当做非法用户,因为访问登录界面时会分配一个Cookie,需要将这个Cookie在发送Post请求时带上,这种使用Session函数处理Cookie的方式之后会很常用。

    3.6 重定向与历史信息

    处理重定向只是需要设置一下allow_redirects字段即可,例如:

    r=requests.get('http://www.baidu.com',allow_redirects=True)

    将allow_redirects设置为True,则是允许重定向;设置为False,则是禁止重定向。如果是允许重定向,可以通过r.history字段查看历史信息,即访问成功之前的所有请求跳转信息。示例如下:

    
     

    import requests
    r = requests.get('http://github.com')
    print r.url
    print r.status_code
    print r.history

    打印结果如下:

    
     

    https://github.com/
    200
    (<Response [301]>,)

    上面的示例代码显示的效果是访问GitHub网址时,会将所有的HTTP请求全部重定向为HTTPS。

    3.7 超时设置

    超时选项是通过参数timeout来进行设置的,示例如下:

    
     

    requests.get('http://github.com', timeout=2)

    3.8 代理设置

    使用代理Proxy,你可以为任意请求方法通过设置proxies参数来配置单个请求:

    
     

    import requests
    proxies = {
        "http""http://0.10.1.10:3128",
        "https""http://10.10.1.10:1080",
    }
    requests.get("http://example.org", proxies=proxies)

    也可以通过环境变量HTTP_PROXY和HTTPS_PROXY?来配置代理,但是在爬虫开发中不常用。你的代理需要使用HTTP Basic Auth,可以使用http://user:password@host/语法:

    
     

    proxies = {
        "http""http://user:pass@10.10.1.10:3128/",
    }


    03

    小结


    本文主要讲解了网络爬虫的结构和应用,以及Python实现HTTP请求的几种方法。希望大家对本文中的网络爬虫工作流程和Requests实现HTTP请求的方式重点吸收消化。

    本文摘编自《Python爬虫开发与项目实战》,经出版方授权发布。

    关于作者:范传辉,资深网虫,Python开发者,参与开发了多项网络应用,在实际开发中积累了丰富的实战经验,并善于总结,贡献了多篇技术文章广受好评。研究兴趣是网络安全、爬虫技术、数据分析、驱动开发等技术。

    640?wx_fmt=jpeg

    Python爬虫开发与项目实战

    扫码购买

    640?wx_fmt=png


    本书特色:

    • 由浅入深,从Python和Web前端基础开始讲起,逐步加深难度,层层递进。

    • 内容详实,从静态网站到动态网站,从单机爬虫到分布式爬虫,既包含基础知识点,又讲解了关键问题和难点分析,方便读者完成进阶。

    • 实用性强,本书共有9个爬虫项目,以系统的实战项目为驱动,由浅及深地讲解爬虫开发中所需的知识和技能。

    • 难点详析,对js加密的分析、反爬虫措施的突破、去重方案的设计、分布式爬虫的开发进行了细致的讲解。

    扫码购买

    640?wx_fmt=png

    展开全文
  • 页面需求:最近遇见一个需求,...其他需求,通过用手机的浏览器(内置,第三方都可)访问一个网页,实现从网页中点击一个链接启动自己的应用,并传递数据。 理解 一个链接地址URL Scheme的协议格式如下: &l...

           页面需求:最近遇见一个需求,点击他人分享的信息,进入一个网页,网页中点击“打开”按钮,若手机中没有此APP则下载,我给的是我们公司官网上的下载地址,若手机中有此APP则打开,打开地址就是我们今天要说的。其他需求,通过用手机的浏览器(内置,第三方都可)访问一个网页,实现从网页中点击一个链接启动自己的应用,并传递数据。

    理解

    一个链接地址URL Scheme的协议格式如下:

    <a href="[scheme]://[host]/[path]?[query]"> 唤起应用 </a>

    scheme:代表Scheme的协议名称(必须)

    host和path可选择添加

    query:代表URL传递的数据

    配置

            首先在AndroidManifest.xml清单文件中找到你的主页Activity配置相关信息

    <activity
            android:name="com.example.helloworld.MainActivity" >
            <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
         
                    <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
    	        <action android:name="android.intent.action.VIEW"/>   
    		<category android:name="android.intent.category.DEFAULT"/>             
    		<category android:name="android.intent.category.BROWSABLE"/>
    		<data android:scheme="zyt" android:host="app" android:pathPrefix="/openwith"/>
            </intent-filter>
    </activity>

    注意:上面两个intent-filter里的配置信息必须分开。

    结果:只需要在AndroidManifest.xml清单文件中配置这些就可以打开APP了。

    验证方式:创建一个网页,建立一个链接例如<a href="zyt://app/openwith?id=20181015">打开app</a>或者把你配置好的地址给后台,直接在项目中验证。和IOS的不一样,我看见我们的IOS可以直接在游览器中输入链接地址打开APP,Android不能,只能经过一个网页。

    获取链接数据:若是你还需要获取地址中的数据,请看下面。

    如果使用Java获取:

    public class SplashActivity extends AppCompatActivity{
    
            @Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
                    Intent intent = getIntent();
    		String scheme = intent.getScheme();
    		Uri uri = intent.getData();
    		if (uri != null) {
    			String host = uri.getHost();
    			String path = uri.getPath();
    			String queryString = uri.getQuery();
                            String test1 = uri.getQueryParameter("arg0");//参数1
                            String test2 = uri.getQueryParameter("arg1");//参数2
                    }
            }
    }

    如果使用WebView访问该网页,获取数据的操作为:

    webView.setWebViewClient(new WebViewClient(){
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    Uri uri=Uri.parse(url);
                    if(uri.getScheme().equals("zyt")&&uri.getHost().equals("app")){
                        String arg0=uri.getQueryParameter("arg0");
                        String arg1=uri.getQueryParameter("arg1");
                    }else{
                        view.loadUrl(url);
                    }
                    return true;
                }
            });

    这里就结束了,若有问题,请多指正。

    展开全文
  • 微信小程序内嵌网页链接

    千次阅读 2019-03-20 16:51:27
    微信小程序内嵌网页链接 微信小程序和浏览器的环境不同,微信小程序中的所有外部连接都必须部署业务域名成功后才能实现跳转访问 不管是a标签的超链接,还是iframe等等都需要在微信公众平台部署业务域名才可访问 ...

    微信小程序内嵌网页链接

    微信小程序和浏览器的环境不同,微信小程序中的所有外部连接都必须部署业务域名成功后才能实现跳转访问

    不管是a标签的超链接,还是iframe等等都需要在微信公众平台部署业务域名才可访问

    若是内嵌微信公众号文章的话则不需要部署,但需要关联微信公众号

    需要提前注意几点:
    1.个人和海外类型的小程序暂不支持使用!
    2.使用微信官方组件web-view,此组件会覆盖页面中所有其他组件,铺满整个小程序页面,除了小程序原生的tabbar
    3.部署业务域名时要求使用的是https
    4.部署业务域名时要求业务域名需经过ICP备案,若是海外域名则无法部署
    使用微信官方组件web-view:
    在这里插入图片描述

    下面来介绍具体步骤:

    内嵌公众号文章

    要求:公众号文章需与小程序需关联

    1.关联公众号

    在这里插入图片描述

    2.使用web-view嵌入公众号文章

    < !-- html -->
     <!-- 指向关联的公众号文章的地址 -->
    <web-view src="https://XXXXXXXXXXXX/"></web-view>
    

    内嵌外部网页

    1.下载部署校验文件

    登陆微信开放平台小程序页面,在“业务域名”中添加,如下图 :
    在这里插入图片描述在这里插入图片描述
    在此下载校验文件,并将校验文件放入指定位置:

    1.业务域名需经过ICP备案,新备案域名需24小时后才可配置。域名格式只支持英文大小写字母、数字及“- ”,不支持IP地址。配置业务域名后,可打开任意合法的子域名。
    2.将文件放置在域名根目录下,例如wx.qq.com,并确保可以访问该文件。
    例如如果想保存的业务为https://test.com/,下载下来的校验文件为AbC.txt,则需要确保https://test.com/AbC.txt能够访问。

    2.添加业务域名

    校验文件部署成功后在此添加业务域名

    注意几点:

    1.业务域名是不需要加前面的https://的
    2.业务域名须填写根域名,例如:如果下载下来的校验文件为AbC.txt,并且https://test.com/AbC.txt能够访问 那么只需填写test.com

    在这里插入图片描述
    目前不少开发者在设置业务域名时,发现检查校验文件失败,可先按照如下步骤进行自查:

    1.业务域名需经过ICP备案,新备案域名需24小时后才可配置。域名格式只支持英文大小写字母、数字及“- ”,不支持IP地址。配置业务域名后,可打开任意合法的子域名。
    2.将文件放置在域名根目录下,例如wx.qq.com,并确保可以访问该文件。
    例如如果想保存的业务为https://test.com/,下载下来的校验文件为AbC.txt,则需要确保https://test.com/AbC.txt能够访问。
    3.校验文件内容错误。校验文件内容一般是非HTML数据,如果下载下来的校验文件内容为HTML数据,一般为登录态过期。请重新登录小程序下载校验文件。
    4.使用4G网络尝试访问链接,确认自身服务器没有拦截请求(常见于设置了白名单或者防火墙的服务器,需开发者自行确认下)
    5.https证书过期。请确保https证书处于有效期内。
    6.使用curl 测试链接,确保curl能够正常访问链接,且curl出来的内容为校验文件内容。
    7.使用time curl https://test.com/abc.txt查看链接时间,建议耗时在1s之内。
    8.请确保url中的文件名与下载下来的文件名大小写一致。如下载的文件是AbC.txt,确保url是https://test.com/AbC.txt,不能是https://test.com/abc.txt
    9.部分用户的服务器配置较陈旧,安全性差(如配置 768位 的 DH),为了保证通信安全,微信后台不支持,请更新服务器配置。
    (1)通过https://cloud.tencent.com/product/tools#userDefined12,检测网址是否支持TLS1.2。
    (2)可通过工具 https://www.ssllabs.com/ssltest/analyze.html 检查自己的服务器,对该工具标红的各项漏洞逐项修补,建议更新配置直到该工具打分为 C及以上 。
    10. 如上述检查都没有问题,请重新下载校验文件重试,确保上传到服务器的文件内容与新下载的文件内容一致。

    3.使用web-view嵌入外部链接

    <!-- html -->
    <!-- 指向嵌入外部链接的地址 -->
    <web-view src="https://XXXXXXXXXXXX/"></web-view>
    

    关闭校验

    最后,如果想暂时预览效果,可在开发者工具中设置关闭校验
    在这里插入图片描述在这里插入图片描述

    展开全文
  • 微信企业号之构造网页授权链接

    千次阅读 2018-12-04 16:09:15
    在开始使用网页授权之前,开发者需要先登录到企业管理端后台,选择“企业应用”选项卡,进入需要使用网页授权的应用并编辑“可信域名”表单项,此选项将用于网页OAuth2.0授权的时候进行安全验证。请注意,这里填写的...

    一.相关介绍

    在企业微信中,我们可以开发企业应用。使用企业应用,我们可以访问到外部网站。那么外部网站如何获取到企业微信共享用户userid以及用户的相关信息,企业微信提供了OAuth的授权登录方式,可以让网页和企业微信共享用户ID,从而免去登录的环节

    二.网页授权的可信域名

    1. 在开始使用网页授权之前,开发者需要先登录到企业管理端后台,选择“企业应用”选项卡,进入需要使用网页授权的应用并编辑“可信域名”表单项,此选项将用于网页OAuth2.0授权的时候进行安全验证。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头
    2. 可信域名配置规范为全域名,且需要通过ICP备案(否则在微信侧jssdk功能失效)。比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.comhttp://qq.com无法进行OAuth2.0鉴权
    3. 域名的验证逻辑说明:由于一个企业可以自定义多个应用,每个应用都可以配置一个安全域名,在做oauth跳转的时候,只需要携带coprid即可,企业微信的后台会遍历该企业下面配置的所有应用并检查其配置的可信域名,只要任意一个应用的可信域名匹配则校验成功。

    三.userid介绍

    UserId用于在一个企业内唯一标识一个用户,通过网页授权接口可以获取到当前用户的UserId信息,如果需要获取用户的更多信息可以调用通讯录管理的成员接口来获取。

    四.接入流程

    企业应用中的URL链接(包括自定义菜单或者消息中的链接),均可通过OAuth2.0验证接口来获取成员的UserId身份信息。注意:此URL的域名,必须完全匹配企业应用设置项中的“可信域名”(如果你的redirect_uri有端口号,那么“可信域名”也必须加上端口号),否则跳转时会提示redirect_uri参数错误。

    通过此接口获取成员身份会有一定的时间开销。对于频繁获取成员身份的场景,建议采用如下方案:
    1、企业应用中的URL链接直接填写企业自己的页面地址
    2、成员操作跳转到步骤1的企业页面时,企业后台校验是否有标识成员身份的cookie信息,此cookie由企业生成
    3、如果没有匹配的cookie,则重定向到OAuth验证链接,获取成员的身份信息后,由企业后台植入标识成员身份的cookie信息
    4、根据cookie获取成员身份后,再进入相应的页面
    在这里插入图片描述

    1. 获取code

    如果企业需要在打开的网页里面携带用户的身份信息,第一步需要构造如下的链接来获取code参数:

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect
    
    参数说明
    参数必须说明
    appid企业的CorpID
    redirect_uri授权后重定向的回调链接地址,请使用urlencode对链接进行处理
    response_type返回类型,此时固定为:code
    scope应用授权作用域。企业自建应用固定填写:snsapi_base
    state重定向后会带上state参数,企业可以填写a-zA-Z0-9的参数值,长度不可超过128个字节
    #wechat_redirect终端使用此参数判断是否需要带上身份信息
    员工点击后,页面将跳转至 redirect_uri?code=CODE&state=STATE,企业可根据code参数获得员工的userid。code长度最大为512字节。
    2.根据code获取成员信息
    请求方式:GET(HTTPS)
    请求地址:
    https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
    
    参数说明
    参数必须说明
    access_token调用接口凭证
    code通过成员授权获取到的code,最大为512字节。每次成员授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
    权限说明: 跳转的域名须完全匹配access_token对应应用的可信域名,否则会返回50001错误。 返回结果: a) 当用户为企业成员时返回示例如下:
    {
       "errcode": 0,
       "errmsg": "ok",
       "UserId":"USERID",
       "DeviceId":"DEVICEID"
    }
    
    参数说明
    errcode返回码
    errmsg对返回码的文本描述内容
    UserId成员UserID。若需要获得用户详情信息,可调用通讯录接口:读取成员
    DeviceId手机设备号(由企业微信在安装时随机生成,删除重装会改变,升级不受影响)
    b) 非企业成员授权时返回示例如下:
    {
       "errcode": 0,
       "errmsg": "ok",
       "OpenId":"OPENID",
       "DeviceId":"DEVICEID"
    }
    
    参数说明
    errcode返回码
    errmsg对返回码的文本描述内容
    OpenId非企业成员的标识,对当前企业唯一
    DeviceId手机设备号(由企业微信在安装时随机生成,删除重装会改变,升级不受影响)
    出错返回示例:
    {
       "errcode": 40029,
       "errmsg": "invalid code"
    }
    

    五.具体代码实现

    1.授权获取code实例

    @GetMapping(value = { "/authOutUser" })
        public String auth(){
            String appid="";//微信企业号里面的appid
            String backUrl ="../page"; //微信回调地址
            String redirect_uri = "";//经urlencode的回调地址
            try {
                redirect_uri = java.net.URLEncoder.encode(backUrl, "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                logger.error("ecdoe error: " + e.getMessage());
            }
            String oauth2Url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
            return "redirect:" + oauth2Url;
        }
    

    2.通过code获取用户信息

     @GetMapping(value = "/page")
        public ModelAndView page(String code) {
            ModelAndView modelAndView=new ModelAndView();
            if(code!=null&&!code.equals("")){
                String accessToken = "";//调用接口凭证
                String url="https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token="+accessToken+"+&code="+code;
                String info = HttpUtil.get(url);
                WxUserInfo userInfo=JSON.parseObject(info,WxUserInfo.class);
                //TODO ... 获取用户信息后进行处理
            }
            modelAndView.setViewName("/handlePage");
            return modelAndView;
        }
    
    展开全文
  • 让别人点击就加你qq的网页链接代码,只要把html改为txt就可以看代码了
  • 网页链接的实现原理

    万次阅读 2018-04-06 16:00:24
    网页链接是指将原本较长的网址转化成较短的网址,从而便于用户的记忆与社交软件上的传播。很多互联网公司都提供了生成短链接的服务,比如新浪微博短网址服务等,本文就来聊聊实现短链接服务的基本原理。 我们...
  • 如何将自己做网页发布到网站让别人可以看到

    万次阅读 多人点赞 2019-06-22 20:33:54
    自从在大学学了HTML和JS之后,一直都在想,怎么将自己写的HTML网页发布到网上像百度一样让任意用户可以访问呢?于是我便了一些尝试,并有了如下收获: 首先,把网站上传到网站让别人访问需要以下东西: 1:域名 2...
  • 浏览器有很多种,有的好用有的不好用,我们当然要用更好用的浏览器打开网页,但是在第三方的应用程序中打卡一些链接,打开的浏览器却不是自己想用的,那怎么办? 首先,我们打开控制面板,将查看方式设置为大图标...
  • 关于google浏览器打不开网页问题之容易被忽略的点

    万次阅读 多人点赞 2019-04-24 23:15:11
    网页,原因网上有好多种,包括什么关闭防火墙、取消高级设置LAN单选框等,我也都试了,搞到最后要崩溃了,后来无意中,我输入一个http://baidu.com然后enter管用了,能打开页面了,欣喜之余发现自己好蠢,明明是让...
  • web应用的时候,对于https不是很了解,按照网络教程部署(参考文章:https://www.cnblogs.com/hld123/p/6343437.html )好https后,浏览器访问风险提示(chrome提示如图,不同浏览器提示内容不一样): ...
  • 源文件中生成了helloworld.war,可根据自己的需求改为合适的名字 2. 连接服务器 下载WinScp软件,打开 再打开自己的服务器,以阿里云举例: 3. 上传war包 把自己的war包,直接拉进右侧webapps的文件内 ...
  • 网页链接实现原理探究

    千次阅读 2018-10-03 13:56:19
    事情是这样的,今天一人问我一个问题,但是我懒得在说,就在网上找了一篇博客通过QQ发送给他,但是在发送链接时我发现之前很长的链接变成了短链接,且这个短链接能够正常访问之前的长链接,好奇之下就有了这篇文章....
  • 微信小程序跳转到其他网页(外部链接)

    万次阅读 多人点赞 2018-03-08 13:48:50
    1.开发的时候,我们难免碰到要跳转到其他网页中去那该怎么实现呢? 2.例如我想点击一个按钮,跳转到百度(百度的网页还是在小程序中打开) 3.wxml 1. index.wxml (按钮页面) &lt;view class='wrapper'&...
  • 网页设计\网页制作常用软件大全

    千次阅读 多人点赞 2014-03-04 12:08:26
    网页设计\网页制作常用软件 一、专业的网页设计、网页制作软件: 1、CorelDraw:通过CorelDRAW9的全方面的设计及网页功能融合到现有的设计方案中,制作矢量的插图、设计及图像,出色地设计公司标志、简报、彩页、...
  • ... ...上面的代码实现了加载html的内容,如果需要点击html的链接,跳转到APP页面,需要加上下面这一行设置: ...如果加上这一行之后会报...如果点击网页里的包含“ABC”的链接,则会进入上面XXX处App的处理逻辑。
  • 7. 网页已经抓取了,那么剩下就分析页面包含的链接了,创建findlinks目录,在其下创建main.go文件,main.go文件代码内容如下: package main import (  "os"  "fmt"  "golang.org/x/net/html" ) func main...
  • 如何超级链接?如何做网页链接

    千次阅读 2009-12-10 18:18:00
    如何做网页链接?怎样才能将word文档中的网页地址成超级链接?工具/自动更正选项/自动套用格式中选上“Internet及网络路径替换为超链接” 工具/自动更正选项/键入时自动套用格式中选上“Internet及网络路径替换为...
  • 如何在手机上访问自己做网页

    万次阅读 2017-12-27 19:04:23
    查看本机的IP地址进入“网络和共享中心”(在控制面板可以进入,右单击左下角那个网络图标也可以进入),然后再点击已链接的网络,进入了“网络连接状态”窗口,点击“详细信息”在详细列表里我们就可以看到网络的
  • 实现将网页链接分享到微信功能

    万次阅读 2017-04-20 09:09:01
    1、在app的build.gradle文件中添加依赖 compile ‘com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+’ 2、在需要的控件(Dialog、Activity)里初始化APP_ID,... private static final String APP_ID = “你申请
  • 最简单的一句代码也能实现 中间的 QQ号可更改 <a href="tencent://...这个直接在腾讯QQ推广里用自己帐号注册一下,然后会生成一段代码,包含唤起QQ的链接;直接拿来用就行! 传送门 QQ推广https://shang.q...
  • 今天开发需要微信分享网页链接自定义图片和文字描述,于是网上各种查找资料和各种看手册,遇到了好多坑,不过啃了半天以后终于把问题解决了,以防以后忘记,今天记录一下; 首先,由于微信已经发布了想要分享链接必须调用...
  • 微信分享网页链接不显示缩略图怎么办 1.认证的公众号 2.备案的域名 有了公众号和域名才能去调用微信接口,也可以使用第三方工具来进行修改,这样即使没有备案的域名和认证的公众号,也可以添加或者修改缩略图和描述...
  • 很多微信推广的朋友经常会遇到一个头疼的问题,自己网页会被同行或者用户恶意投诉举报,导致域名被微信拦截后报红,用户无法访问。 那么当大家遇到这个问题的时候应该怎么办呢?不用急,下面分享给大家一种...
  • 通过网页链接调用QQ临时会话实现

    万次阅读 2017-10-14 13:02:07
    笔者看到有些网站通过点击链接,可以直接调用QQ,并且通过次链接发起临时会话联系客服。因此对其实现方式感到好奇,于是着手去实现此功能。借助此平台把实现的方法分享给大家。 1、首先准备个QQ号作为信息接收的对象...
  • 链接: http://wpa.qq.com/msgrd?v=3&amp;amp;uin=QQ号码&amp;amp;site=qq&amp;amp;menu=yes eg:http://wpa.qq.com/msgrd?v=3&amp;amp;uin=1186154608&amp;amp;site=qq&amp;amp;menu=yes...
  • 网页点击链接,跳转qq添加好友

    万次阅读 多人点赞 2018-09-17 10:46:44
    一、网页版本点击跳转到添加好友界面:(直接用下面的链接地址,将qq号改成自己的即可) http://wpa.qq.com/msgrd?v=3&uin=1570915261&site=qq&menu=yes 测试:点击添加qq 效果: 二、调用客户端...
  • 我们如何使用浏览器网页链接打开本地 exe 客户端程序? 步骤如下 新建注册表文件 szztClient.reg, 客户端的名称和客户端的地址可以自己定义。 [HKEY_CLASSES_ROOT\szztClient] @="szztClientProtocol" "URL ...
  • 写手机端网页,怎么添加跳转到QQ的链接
  • 以前我仅仅把网页开始的地方放一个不可见的图片,后来发现没有效果。 现在我们开始: 原料:GetwxLink 微信公众号: 步骤一:绑定域名 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 274,001
精华内容 109,600
关键字:

如何自己做网页链接