Python爬虫模块使用方法
Python爬虫模块使用
requests模块
Requests模块是在Python内置模块的基础上进行了高度的封装,主要用来发送HTTP网络请求,可以轻而易举的完成浏览器的任何操作。 Requests模块比urllib2模块更简洁。
使用步骤
-
可以直接使用python pip进行安装
>>>pip install requests
-
导入模块
import requests
-
定制请求头headers
headers = { 'Host': 'node16.sleap.com:8089', 'Referer': 'http://node16.sleap.com:8089/leapid-admin/view/login.html?cb=http%3A%2F%2Fnode15.sleap.com%3A2017', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36' } r = requests.get(url, headers=headers)
-
发送请求
#######r为Response对象,我们可以从这个对象中获取请求返回的信息。########### r = requests.get('https://api.github.com/events') r = requests.post('http://httpbin.org/post', data = {'key':'value'}) r = requests.put('http://httpbin.org/put', data = {'key':'value'}) r = requests.delete('http://httpbin.org/delete') r = requests.head('http://httpbin.org/get') r = requests.options('http://httpbin.org/get')
-
传递URL参数
httpbin.org/get?key=val。
#####Requests 允许你使用 params 关键字参数,以一个字符串字典来提供这些参数##### payload = {'key1': 'value1', 'key2': 'value2'} r = requests.get("http://httpbin.org/get", params=payload)
通过打印输出该 URL,你能看到 URL 已被正确编码:
>>> print(r.url) http://httpbin.org/get?key1=value1&key2=value2&key2=value3
-
响应内容
Requests 会自动解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。
>>> r = requests.get('https://api.github.com/events') >>> r.text u'[{"repository":{"open_issues":0,"url":"https://github.com/...
你可以找出 Requests 使用了什么编码,并且能够使用 r.encoding 属性来改变它:
>>> r.encoding 'utf-8' >>> r.encoding = 'ISO-8859-1'
-
JSON响应内容
Requests 中也有一个内置的 JSON 解码器,助你处理 JSON 数据:
>>> r = requests.get('https://api.github.com/events') >>> r.json() [{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...
如果 JSON 解码失败, r.json() 就会抛出一个异常。例如,响应内容是 401 (Unauthorized),尝试访问 r.json() 将会抛出 ValueError: No JSON object could be decoded 异常。
-
复杂的POST请求
发送一些编码为表单形式的数据——非常像一个 HTML 表单。要实现这个,只需简单地传递一个字典给 data 参数。你的数据字典在发出请求时会自动编码为表单形式:
>>> payload = {'key1': 'value1', 'key2': 'value2'} >>> r = requests.post("http://httpbin.org/post", data=payload) >>> print(r.text) { ... "form": { "key2": "value2", "key1": "value1" }, ... }
-
响应状态码
我们可以通过r.status_code检测响应状态码:
>>> r = requests.get('http://httpbin.org/get') >>> r.status_code 200
-
响应头
>>> r.headers
-
Cookie
如果某个响应中包含一些 cookie,你可以快速访问它们:
>>> url = 'http://example.com/some/cookie/setting/url' >>> r = requests.get(url) >>> r.cookies['example_cookie_name'] 'example_cookie_value'
发送得到的cookie到服务器,可以使用
cookie
参数:>>> url = 'http://httpbin.org/cookies' >>> cookies = dict(cookies_are='working') >>> r = requests.get(url, cookies=cookies) >>> r.text '{"cookies": {"cookies_are": "working"}}'
Cookie 的返回对象为 RequestsCookieJar,它的行为和字典类似,但接口更为完整,适合跨域名跨路径使用。你还可以把 Cookie Jar 传到 Requests 中:
>>> jar = requests.cookies.RequestsCookieJar() >>> jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies') >>> jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere') >>> url = 'http://httpbin.org/cookies' >>> r = requests.get(url, cookies=jar) >>> r.text '{"cookies": {"tasty_cookie": "yum"}}'
-
会话对象
会话对象让你能够跨请求保持某些参数。它也会在同一个 Session 实例发出的所有请求之间保持 cookie,所以如果你向同一主机发送多个请求,底层的 TCP 连接将会被重用,从而带来显著的性能提升。
会话对象具有主要的 Requests API 的所有方法。
跨请求保持一些 cookie:s = requests.Session() s.get('http://httpbin.org/cookies/set/sessioncookie/123456789') r = s.get("http://httpbin.org/cookies") print(r.text) # '{"cookies": {"sessioncookie": "123456789"}}'
-
请求与响应对象
任何时候进行了类似
requests.get()
的调用,你都在做两件主要的事情。其一,你在构建一个Request
对象, 该对象将被发送到某个服务器请求或查询一些资源。 其二,一旦requests
得到一个从服务器返回的响应就会产生一个Response对象。该响应对象包含服务器返回的所有信息,也包含你原来创建的Request对象。
如果想访问服务器返回给我们的响应头部信息,可以这样做:>>> r.headers
如果想得到发送到服务器的请求的头部,我们可以简单地访问该请求,然后是该请求的头部:
>>> r.request.headers
urllib模块
urllib 库用于操作网页 URL,并对网页的内容进行抓取处理。
urllib 包 包含以下几个模块:
- urllib.request - 打开和读取 URL。
- urllib.error - 包含 urllib.request 抛出的异常。
- urllib.parse - 解析 URL。
- urllib.robotparser - 解析 robots.txt 文件。
使用步骤
-
打开一个 URL
urlopen ,然后使用 read() 函数获取网页的 HTML 实体代码。
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None,capath=None, cadefault=False, context=None) # url:url 地址。 # data:发送到服务器的其他数据对象,默认为 None。 # timeout:设置访问超时时间。 # cafile 和 capath:cafile 为 CA 证书, capath 为 CA 证书的路径,使用 HTTPS 需要用到。 # cadefault:已经被弃用。 # context:ssl.SSLContext类型,用来指定 SSL 设置。 # read() 是读取整个网页内容,我们可以指定读取的长度。
-
读取网页内容
除了 read() 函数外,还包含以下两个读取网页内容的函数:
#readline() - 读取文件的一行内容 from urllib.request import urlopen myURL = urlopen("https://www.runoob.com/") print(myURL.readline()) #读取一行内容 #readlines() - 读取文件的全部内容,它会把读取的内容赋值给一个列表变量。 from urllib.request import urlopen myURL = urlopen("https://www.runoob.com/") lines = myURL.readlines() for line in lines: print(line)
-
判断网页正常访问
#我们在对网页进行抓取时,经常需要判断网页是否可以正常访问,这里我们就可以使用 getcode() 函数获取网页状态码,返回 200 说明网页正常,返回 404 说明网页不存在: import urllib.request myURL1 = urllib.request.urlopen("https://www.runoob.com/") print(myURL1.getcode()) # 200 try: myURL2 = urllib.request.urlopen("https://www.runoob.com/no.html") except urllib.error.HTTPError as e: if e.code == 404: print(404) # 404
-
抓取的网页保持到本地
#如果要将抓取的网页保持到本地,可以使用 Python3 File write() 方法 from urllib.request import urlopen myURL = urlopen("https://www.runoob.com/") f = open("runoob_urllib_test.html", "wb") content = myURL.read() # 读取网页内容 f.write(content) f.close() #执行以上代码,在本地就会生成一个 runoob_urllib_test.html 文件,里面包含了网页的内容
-
URL 的编码与解码
#编码与解码可以使用 urllib.request.quote() 与 urllib.request.unquote()方法 import urllib.request encode_url = urllib.request.quote("https://www.runoob.com/") # 编码 print(encode_url) unencode_url = urllib.request.unquote(encode_url) # 解码 print(unencode_url) #out https%3A//www.runoob.com/ https://www.runoob.com/
-
模拟头部信息
#我们抓取网页一般需要对 headers(网页头信息)进行模拟,这时候需要使用到urllib.request.Request 类 class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None) #url:url 地址。 #data:发送到服务器的其他数据对象,默认为 None。 #headers:HTTP 请求的头部信息,字典格式。 #origin_req_host:请求的主机地址,IP 或域名。 #unverifiable:很少用整个参数,用于设置网页是否需要验证,默认是False。。 #method:请求方法, 如 GET、POST、DELETE、PUT等。
-
异常
urllib.error 模块为 urllib.request 所引发的异常定义了异常类,基础异常类是 URLError。
urllib.error 包含了两个方法,URLError 和 HTTPError。
URLError 是 OSError 的一个子类,用于处理程序在遇到问题时会引发此异常(或其派生的异常),包含的属性 reason 为引发异常的原因。
HTTPError 是 URLError 的一个子类,用于处理特殊 HTTP 错误例如作为认证请求的时候,包含的属性 code 为 HTTP 的状态码, reason 为引发异常的原因,headers 为导致 HTTPError 的特定 HTTP 请求的 HTTP 响应头。
#对不存在的网页抓取并处理异常 import urllib.request import urllib.error myURL1 = urllib.request.urlopen("https://www.runoob.com/") print(myURL1.getcode()) # 200 try: myURL2 = urllib.request.urlopen("https://www.runoob.com/no.html") except urllib.error.HTTPError as e: if e.code == 404: print(404) # 404
-
解析
urllib.parse 用于解析 URL
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True) #urlstring 为 字符串的 url 地址,scheme 为协议类型 #allow_fragments 参数为 false,则无法识别片段标识符。相反,它们被解析为路径,参数或查询组件的一部分,并 fragment 在返回值中设置为空字符串。 from urllib.parse import urlparse o = urlparse("https://www.runoob.com/?s=python+%E6%95%99%E7%A8%8B") print(o) #out ParseResult(scheme='https', netloc='www.runoob.com', path='/', params='', query='s=python+%E6%95%99%E7%A8%8B', fragment='') #从结果可以看出,内容是一个元组,包含 6 个字符串:协议,位置,路径,参数,查询,判断 #还可以直接读取协议内容 from urllib.parse import urlparse o = urlparse("https://www.runoob.com/?s=python+%E6%95%99%E7%A8%8B") print(o.scheme) #out https
urllib.robotparser 用于解析 robots.txt 文件。
robots.txt(统一小写)是一种存放于网站根目录下的 robots 协议,它通常用于告诉搜索引擎对网站的抓取规则。
urllib.robotparser 提供了 RobotFileParser 类,这个类提供了一些可以读取、解析 robots.txt 文件的方法。
class urllib.robotparser.RobotFileParser(url='') #set_url(url) 设置 robots.txt 文件的 URL。 #read() 读取 robots.txt URL 并将其输入解析器。 #parse(lines) 解析行参数。 #can_fetch(useragent, url) 如果允许 useragent 按照被解析 robots.txt 文件中的规则来获取 url 则返回 True。 #mtime() 返回最近一次获取 robots.txt 文件的时间。 这适用于需要定期检查 robots.txt 文件更新情况的长时间运行的网页爬虫。 #modified() 将最近一次获取 robots.txt 文件的时间设置为当前时间。 #crawl_delay(useragent) 为指定的 useragent 从 robots.txt 返回 Crawl-delay 形参。 如果此形参不存在或不适用于指定的 useragent 或者此形参的 robots.txt 条目存在语法错误,则返回 None。 #request_rate(useragent) 以 named tuple RequestRate(requests, seconds) 的形式从 robots.txt 返回 Request-rate 形参的内容。 如果此形参不存在或不适用于指定的 useragent 或者此形参的 robots.txt 条目存在语法错误,则返回 None。 #site_maps() - 以 list() 的形式从 robots.txt 返回 Sitemap 形参的内容。 如果此形参不存在或者此形参的 robots.txt 条目存在语法错误,则返回 None。
高效爬虫
python里面共有进程、线程、协程三个层次概念,爬虫就是选择:单线程爬取,单线程+协程爬取,多线程爬取,多线程 + 协程爬取,多进程爬取,多进程 + 协程爬取6种组合方案。
存在依赖关系的协程之间是不能够被并发执行的,不存在依赖关系的协程之间是能够被并发执行的。
由于GIL锁的存在,使得线程没法并行执行,只能并发执行。而在并发的情况下,协程的创建、切换开销远远小于线程。所以使用协程而不是使用线程在Python里面是更优的解决方案。
最高效的爬取方案?答案是: 多进程 + 协程。
协程的方案肯定要比多线程快,因为协程的切换开销非常之小。而且协程的并发度可以非常高。我们一般开线程也就几十个线程,协程的并发度可以达到999个。但协程的缺点就是没法并行运行。
所以多进程 + 协程的方案既利用了并行,又利用了并发。完美了利用了多核,同时又让每一个线程的时间片被充分的利用。