python爬虫笔记

a 夏天 提交于 2020-01-30 00:54:14

爬虫

http://httpbin.org/  验证请求

1.urllib库(python3)

python内置的HTTP请求库

urllib.request  请求模块 (https://yiyibooks.cn/xx/python_352/library/urllib.request.html#module-urllib.request)

urllib.error      异常处理模块(https://yiyibooks.cn/xx/python_352/library/urllib.error.html#module-urllib.error)

urllib.parse    url解析模块(https://yiyibooks.cn/xx/python_352/library/urllib.parse.html#module-urllib.parse)

urllib.robotparser    robots.txt解析模块(https://yiyibooks.cn/xx/python_352/library/urllib.robotparser.html#module-urllib.robotparser)

 

请求:

import urllib.request

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None) 

  • url    请求的网址
  • data  加上以post请求发送,不加以get请求发送
  • [timeout, ]*     设置请求时间   超过时间报TIME OUT异常
  • cafile      
  • capath
  • cadefault
  • context

响应 

import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(type(response))#响应类型
print(response.status)#状态码
print(response.getheaders())#响应头 返回元组组成的列表
print(response.getheader('Server'))#获取特定的响应头
print(response.read().decode('utf-8'))#获得响应体

  也可以根据请求来获得响应

from urllib import request, parse
url = 'http://httpbin.org/post'
headers = {
    'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
    'Host': 'httpbin.org'
}
dict = {
    'name': 'Germey'
}
data = bytes(parse.urlencode(dict), encoding='utf8')
req = request.Request(url=url, data=data, headers=headers, method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))

 Handler

代理ip

proxy_handler = urllib.request.ProxyHandler({
    'http': 'http://127.0.0.1:9743',
    'https': 'https://127.0.0.1:9743'
})
opener = urllib.request.build_opener(proxy_handler)
response = opener.open('http://httpbin.org/get')
print(response.read())

cookie(保持登录会话信息

import http.cookiejar, urllib.request
cookie = http.cookiejar.CookieJar()#也可以修改CookieJar把cookie保存到本地文件(MozillaCookieJar或LWPCookieJar)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
for item in cookie:
    print(item.name+"="+item.value)

 异常

from urllib import request, error
try:
    response = request.urlopen('http://bubaidu.com/index.htm')
except error.HTTPError as e:
    print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
    print(e.reason)
else:
    print('Request Successfully')

url解析

 

urlparse

 

urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)#urlstring:请求地址,scheme:约束 协议,allow_fragments:将fragment拼接到前面有数据的

 

 

from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment', scheme='https',allow_fragments=False)
print(type(result),result)
---------------------------------------------------------------------
<class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5#comment', fragment='')

 

urlunparse(将url和参数请求等进行拼接

urljoin(将两个url进行拼接,以后面的为基准)

urlencode(将字典拼接为url的请求参数

=============================================================================================

2.requests库

(request库在urllib3的基础上进行加强,推荐使用request库)

pip install requests
import requests
response = requests.get('https://www.baidu.com/')
print(type(response))
print(response.status_code)#响应状态码
print(type(response.text))
print(response.text)#响应体
print(response.cookies)#cookies

请求

  get请求

requests.get(url, params=None, **kwargs)#params以字典形式添加请求参数,也可以直接在url中写参数#可以添加headers(有些网址不添加headers会报500的错误)

 headers = {
 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
 }
 response = requests.get("https://www.zhihu.com/explore", headers=headers)

 

    解析json

import requests
import json
response = requests.get("http://httpbin.org/get")
print(type(response.text))
print(response.json())
print(json.loads(response.text))#用json转码,结果和response.json()返回结果一样
print(type(response.json()))

    获取二进制数据(用于下载图片等)

import requests
response = requests.get("https://github.com/favicon.ico")
with open('favicon.ico', 'wb') as f:#将图片保存到本地
    f.write(response.content)#获得图片的二进制内容并写入
    f.close()

  基本post请求

import requests
data = {'name': 'germey', 'age': '22'}
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
}
response = requests.post("http://httpbin.org/post", data=data, headers=headers)
print(response.json())

响应

 

response = requests.get('http://www.jianshu.com')
print(type(response.status_code), response.status_code)#状态码
print(type(response.headers), response.headers)#响应头(字典)
print(type(response.cookies), response.cookies)#cookies(列表)
print(type(response.url), response.url) #
print(type(response.history), response.history)#访问的历史记录

 

文件上传

files = {'file': open('favicon.ico', 'rb')}
response = requests.post("http://httpbin.org/post", files=files)
print(response.text)

会话维持(模拟登陆)

 

s = requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456789')
response = s.get('http://httpbin.org/cookies')
print(response.text)

证书验证(在以https协议请求时,会先检测ssl是否是合法的)

import requests
from requests.packages import urllib3
urllib3.disable_warnings()
response = requests.get('https://www.12306.cn', verify=False)
print(response.status_code)

代理

proxies = {
  "http": "http://127.0.0.1:9743",
  "https": "https://127.0.0.1:9743",
}
response = requests.get("https://www.taobao.com", proxies=proxies)
print(response.status_code)

  也可以使用socks代理(pip3 install 'requests[socks]')

proxies = {
    'http': 'socks5://127.0.0.1:9742',
    'https': 'socks5://127.0.0.1:9742'
}

超时设置

response = requests.get("http://httpbin.org/get", timeout = 0.5)

登录验证设置

r = requests.get('http://120.27.34.24:9001', auth=('user', '123'))
print(r.status_code)

异常处理

import requests
from requests.exceptions import ReadTimeout, ConnectionError, RequestException
try:
    response = requests.get("http://httpbin.org/get", timeout = 0.5)
    print(response.status_code)
except ReadTimeout:
    print('Timeout')
except ConnectionError:
    print('Connection error')
except RequestException:
    print('Error')

===================================================================================================================

3.BeautifulSoup库

pip install BeautifulSoup4

解析库

解析器使用方法优势劣势
Python标准库 BeautifulSoup(markup, "html.parser") Python的内置标准库、执行速度适中 、文档容错能力强 Python 2.7.3 or 3.2.2)前的版本中文容错能力差
lxml HTML 解析器 BeautifulSoup(markup, "lxml") 速度快、文档容错能力强 需要安装C语言库
lxml XML 解析器 BeautifulSoup(markup, "xml") 速度快、唯一支持XML的解析器 需要安装C语言库
html5lib BeautifulSoup(markup, "html5lib") 最好的容错性、以浏览器的方式解析文档、生成HTML5格式的文档 速度慢、不依赖外部扩展

基本使用

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.prettify())#格式化,补全代码
print(soup.title.string)#输出title标签中的内容
print(soup.title)#获取titile标签及其包裹的内容
print(soup.title.name)#获取名称  结果为title
print(soup.p.attrs['name'])#获取属性字段为的name的值
print(soup.p['name'])#获取获取属性字段为的name的值
print(soup.p.string)#获取p标签中的内容

  也可以嵌套选择

print(soup.head.title.string)

  获得子节点和子孙节点方法

#获得p标签子节点
    soup.p.contents#列表
    soup.p.children#迭代器
#获得p标签所有子孙节点
    soup.p.descendants#迭代器

  例:

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.p.children)
for i, child in enumerate(soup.p.children):
    print(i, child)

  获得父节点和祖先节点

soup.a.parent#获取a标签的父节点
soup.a.parents#获取a标签的祖先节点(迭代器)

  获取兄弟节点

soup.a.next_siblings#获取a标签后面的兄弟节点(迭代器)
soup.a.previous_siblings#获取a标签前面的兄弟节点(迭代器)

标准选择器

find_all( name , attrs , recursive , text , **kwargs )#可根据标签名、属性、内容查找文档
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all('ul'))#获取ul标签及内容,返回结果为列表

print(soup.find_all(attrs={'id': 'list-1'}))#获取id为list-1的标签体,返回结果为列表
print(soup.find_all(id='list-1'))#特殊的字段可以用这种形式,获取id为list-1的标签体,返回结果为列表
print(soup.find_all(class_='element'))#class比较特殊

print(soup.find_all(text='Foo'))#返回的结果:内容为Foo的元组 例['Foo', 'Foo'] (多用于匹配内容)

 

find( name , attrs , recursive , text , **kwargs )#find返回单个元素,find_all返回所有元素
find_parents()#返回所有祖先节点
find_parent()# 返回直接父节点。

find_next_siblings()#返回后面所有兄弟节点
find_next_sibling()#返回后面第一个兄弟节点。

find_previous_siblings()#返回前面所有兄弟节点
find_previous_sibling()#返回前面第一个兄弟节点。

find_all_next()#返回节点后所有符合条件的节点
find_next()#返回第一个符合条件的节点

find_all_previous()#返回节点后所有符合条件的节点
find_previous()#返回第一个符合条件的节点

 

 

CSS选择器

 通过select()直接传入CSS选择器即可完成选择

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.select('.panel .panel-heading'))
print(soup.select('ul li'))
print(soup.select('#list-2 .element'))
print(type(soup.select('ul')[0]))
  获取属性
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
for ul in soup.select('ul'):
    print(ul['id'])
    print(ul.attrs['id'])
 获取内容
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
for li in soup.select('li'):
    print(li.get_text())

总结

  • 推荐使用lxml解析库,必要时使用html.parser
  • 标签选择筛选功能弱但是速度快
  • 建议使用find()、find_all() 查询匹配单个结果或者多个结果
  • 如果对CSS选择器熟悉建议使用select()
  • 记住常用的获取属性和文本值的方法

===================================================================================================================================

4.pyquery库

(pyquery比BeautifulSoup更加简易,熟悉jquery推荐使用pyquery)

from pyquery import PyQuery as pq
doc = pq(html)
print(doc('li'))#打印所有li标签及内容(css选择器)

  URL初始化

doc = pq(url='http://www.baidu.com')#将网页html代码作为参数

  文件初始化

doc = pq(filename='demo.html')#这样写文件和代码在同一路径

基本CSS选择器

from pyquery import PyQuery as pq
doc = pq(html)
print(doc('#container .list li'))
from pyquery import PyQuery as pq
doc = pq(html)
items = doc('.list')
#查找元素
lis = items.find('li')#查找子元素为li标签的
lis2 = items.children('.active')#查找所有的直接子元素class为active的

container = items.parent()#获取直接父元素
parents = items.parents()#获取父节点及所有祖先节点,也可以添加选择器

li = doc('.list .item-0.active')#.item-0.active表示一个整体 例:class="item-0 active"
print(li.siblings())#获取所有的兄弟节点

遍历

from pyquery import PyQuery as pq
doc = pq(html)#如果doc('li')获得为一个值则可以直接操作,如果多个可以进行遍历
lis = doc('li').items()#转换为generator类型
print(type(lis))
for li in lis:
    print(li)

获取信息

from pyquery import PyQuery as pq
doc = pq(html)
a = doc('.item-0.active a')

print(a.attr('href'))#获取属性为href的值
print(a.attr.href)#获取属性为href的值

print(a.text())#获取文本

print(a.html())#获取HTML

DOM操作

from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.item-0.active')

#addClass、removeClass
li.removeClass('active')#移除active属性
li.addClass('active')#添加active属性

#attr、css
li.attr('name', 'link')#修改name属性的值(没有则添加,有则修改)
li.css('font-size', '14px')#添加style属性并添加css样式

#remove
html = '''
<div class="wrap">
    Hello, World
    <p>This is a paragraph.</p>
 </div>
'''
doc = pq(html)
wrap = doc('.wrap')
print(wrap.text())#Hello, World           This is a paragraph.
wrap.find('p').remove()#移除
print(wrap.text())#Hello, World

其他DOM方法

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!