脚本编写相关的Python库

Requests库

requests.request(method, url, **kwargs)是最基本的方法,其它方法封装内部大多为request

我们通常用r = requests.get(url)获取网页信息,其会构造一个向服务器请求资源的Request对象,对象由Requests库内部生成;get()函数返回的内容表示为rr是一个Response对象,包含从服务器返回的所有相关资源。

完整方法:requests.get(url, params=None, **kwargs),其中,url为链接,params是字典或字节流格式,**kwargs是12个控制访问的参数。

request参数(使用时写成r.request.params等):

  • params:字典或字节序列,作为参数增加到url中
  • data:字典、字节序列或文件对象,作为Request的内容
  • json:JSON格式的数据,作为Request的内容
  • headers:字典,HTTP定制头
  • files:字典类型,传输文件
  • timeout:设定超时时间(单位:秒)
  • proxies:字典类型,设定访问代理服务器,可以增加登录认证
  • allow_redirects:True/False,默认为True,重定向开关
  • stream:True/False,默认为True,获取内容立即下载开关
  • verify:True/False,默认为True,认证SSL证书开关
  • cert:本地SSL证书路径
  • cookies:字典或CookieJar,Request中的cookie
  • auth:元组,支持HTTP认证功能

response对象:

r.status_code:状态码,状态码为200表示访问成功,否则(比如404)表示访问失败。

r.headers:头部信息

r.text:url的页面内容

r.content:url相应内容的二进制形式

r.encoding:从HTTP header中猜测的响应内容编码方式(如果header中不存在charset,则认为编码为ISO-8859-1)

r.apparent_encoding:从内容中分析出的相应内容编码方式(备选方式)(一般更加准确)

r.raise_for_status():如果状态码不是200,则产生异常requests.HTTPError(如404表示失败)

爬取网页的通用代码框架:

import requests

def getHTMLText(url):
    try:
        r = requests.get(url, timeout = 30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "ERROR"

if __name__ == "__main__":
    url = "http://www.baidu.com"
    print(getHTMLText(url))

HTTP协议

HTTP,Hypertext Transfer Protocol,超文本传输协议

HTTP协议采用URL作为定位网络资源的标识。

URL格式:http://host[:port][path]

  • host:合法的Internet主机域名或IP地址
  • port:端口号(默认为80)
  • path:资源路径

其它方法:

requests.head():获取HTML网页头信息(可以用r.headers获取头部信息的内容,但是不能使用r.text

requests.post(url, data = [content]):向HTML网页提交POST请求,附加新的数据

requests.put(url, data = [content]):向HTML网页提交PUT请求,与POST使用类似,不过功能是覆盖原URL位置的资源

requests.patch():向HTML网页提交局部修改请求

requests.delete():向HTML网页提交删除请求

Robots协议:

网站的robots协议一般放在根目录,如http://www.baidu.com/robots.txt

基本语法:

#注释:*表示所有,/表示根目录
User-agent: * (表示限制哪些爬虫)
Disallow: / (表示不允许访问的目录)

修改user-agent:

网站可能通过对网站访问的HTTP的头来判断访问是否由爬虫引起,但是我们可以更改头部信息,即修改r.request.headers(如r = requests.get(url, headers = {'user-agent': 'Mozilla/5.0'}))来进行访问。

搜索引擎关键字接口:

比如:http://www.baidu.com/s?wd=keyword、http://www.so.com/s?q=keyword

我们把信息加在params里即可:

import requests
kv = {'wd': 'Python'}
kv1 = {'user-agent': 'Mozilla/5.0'}
r = requests.get("http://www.baidu.com/s?ie=UTF-8", params = kv, headers = kv1)
print(r.request.url)

输出的结果:

https://www.baidu.com/s?ie=UTF-8&wd=Python

爬取图片:

import requests
import os
root = "D://pics/"
url = "https://tva4.sinaimg.cn/large/0072Vf1pgy1foenqvqwvqj31hc0xc7aj.jpg"
path = root + url.split('/')[-1] #命名为网站上的原文件名,即最后一个'/'的后面的内容
if not os.path.exists(root):
	os.mkdir(root)
if not os.path.exists(path):
	r = requests.get(url)
	with open(path, 'wb') as f:#打开文件,定义为标识符f
		f.write(r.content)##content为二进制内容
		f.close()
		print("Picture Saved Successfully!")
else:
	print("Picture Exists already!")

(视频和音频也是一样的)

信息标记和提取

三种信息标记:

XML(eXtensible Markup Language)(用于Internet上的信息交互):<name ...> ... </name><name ... /><!--...-->

JSON(JavaScript Object Notation)(用于移动应用云端和节点的信息通信,无注释):形式为键值对。如果一个键对应多个值,用[]括起来;如果有嵌套,用{}括起来。

(例:"key": "value""key": ["value1", "value2"]"key": {"subkey": "subvalue"}

YMAL(YAML Ain't Markup Language)(用于系统配置文件,易读、有注释):形式为无类型键值对,即key: value,用缩进表示所属关系,如:

name:
	newname: name1
	oldname: name2

-表示并列关系,如:

name:
- name1
- name2

#进行注释,用|表达大段数据。

提取信息的一般方法:

  • 完整解析信息的标记形式,再提取关键信息(BeautifulSoup库)
  • 直接搜索关键信息(Re库)

Beautiful Soup库

~是解析html和xml文件的功能库。

引用:from bs4 import BeautifulSoup(简写为bs4,导入BeautifulSoup这个类)(注意大写)

解析:soup = BeautifulSoup(r.text, "html.parser")即解析后的内容(会转成UTF-8)

(或者soup2 = BeautifulSoup(open("D://a.html"), "html.parser")

soup.prettify()可返回排版后的文件内容)

其它解析器:

lxml的HTML解析器:BeautifulSoup(mk, 'lxml')

lxml的XML解析器:BeautifulSoup(mk, 'xml')

以上两个都需要pip install lxml

html5lib的解析器:BeautifulSoup(mk, 'html5lib')

需要pip install html5lib

HTML代码是tag组成的树形结构,用<tag>...</tag>括起来。

soup.<tag>可以调用<tag>的内容,如soup.title,可以返回<title>TITLE_CONTENT</title>

如果存在相同名字的tag时,用soup.<tag>只能返回第一个。

<tag>.parent可以调用上一层tag,<tag>.name可以得到tag名字,如:

soup.a.name(就是a)

soup.a.parent.namesoup.a.parent.parent.name:a的祖先tag的名字

soup.attrs获取tag的属性信息(字典类型)

soup.string表示尖括号之间的内容(类型为bs4.element.NevigableString

在HTML代码中,<p><!...!></p>表示注释,而我们调用soup.p.string时,会得到注释的内容,而且和上面不同的是,注释的类型是bs4.element.Comment,所以我们可以通过string的类型判断这一段是不是注释。

tag树的遍历:

tag.contents:子节点的列表(也包含字符串节点,比如'\n'换行酱紫的,用isinstance(tag, bs4.element.Tag)进行判断(需要直接import bs4))

tag.children:子节点的迭代类型

tag.descendants:子孙节点的迭代类型

tag.parent:父节点(如果没有就是None

tag.parents:祖先节点的迭代类型

tag.next_sibling:按照HTML文本顺序的下一个兄弟节点

tag.previous_sibling:按照HTML文本顺序的上一个兄弟节点

tag.next_siblings:按照HTML文本顺序的后面的所有兄弟节点的迭代类型

tag.previous_siblings:按照HTML文本顺序的前面的所有兄弟节点的迭代类型

tag.find_all(name, attrs, recursive, string, **kwargs):查找,返回列表

name为检索的tag名字;如果要查找多种tag,可以传入一个列表;如果给出的标签名称是True,那么会返回所有标签信息;如果我们要求查找“**开头的tag”,可以利用re库。

attrs限制属性,可以查找属性值,也可以查找键值对,比如:soup.find_all('p', 'xxx')或者soup.find_all(att = 'xxx')

recursive:是否检索全部子孙,默认为TrueFalse即只检索子节点)。

string指对<>...</>中间区域进行字符串检索(返回的只有中间的字符串的列表)。

简写:tag.find_all(...)可简写作tag(...)soup.find_all(...)也可以简写作soup(...)

扩展:

<>.find():只返回一个结果

<>.find_parents():在祖先节点中查找,列表类型

<>.find_parent():在祖先节点中查找,只返回一个结果

find_next_siblings()find_next_sibling()find_previous_siblings()find_previous_sibling()同理。

Re库

RE(Regular Expression):正则表达式

正则表达式语法:

  • .:表示任何字符

  • []:字符集,[abc]表示a、b、c;[a-z]表示所有小写字母

  • [^]:非字符集,[^abc]表示非a、b、c的所有字符

  • *:前一个字符零次或多次扩展,如abc*表示ababcabcc……

  • +:前一个字符一次或更多次数的扩展,如abc+表示abcabcc……

  • ?:前一个字符零次或一次扩展,如abc?表示ababc

  • |:左右表达式任意一个,如abc|def表示abcdef

  • {m}:前一个字符的m次扩展,ab{2}c表示abbc

  • {m,n}:前一个字符的m~n次扩展,ab{1,2}c表示abcabbc

  • ^:匹配字符串开头

  • $:匹配字符串结尾

  • ():分组标记,内部只能使用|

  • \d:等价于[0-9]

  • \w:等价于[A-Za-z0-9]

应用:

  • 字母组成的字符串:^[A-Za-z]+$

  • 0~255的数字:([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])

    (0-99|100-199|200-249|250-255)

正则表达式的表示类型是raw string(即不包含转义符的字符串),表示为r'text'

常用函数:

  • re.search(RawString, String, flags = 0):在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象

    flags为控制标记,常用标记有:

    • re.I:忽略大小写
    • re.M^允许把每行的开头作为匹配的开始位置
    • re.S.能匹配任意字符(原本不能匹配换行符)
  • re.match(RawString, String, flags = 0):在一个字符串的开始位置起匹配正则表达式,返回match对象

  • re.findall(RawString, String, flags = 0):以列表形式返回所有匹配的字符串

  • re.split(RawString, String, maxsplit = 0, flags = 0):将字符串按正则表达式匹配结果进行分割,将匹配的部分去掉,返回列表(maxsplit表示最大分割数,剩余部分作为最后一个元素输出)

  • re.finditer(RawString, String, flags = 0):返回一个匹配结果的迭代类型,迭代元素为match对象

  • re.sub(RawString, repl, String, count = 0, flags = 0):将所有匹配的子串替换,返回替换后的子串(repl表示替换字符串,count表示最大替换次数)

match对象的属性:

  • .string:String
  • .re:RawString
  • .pos:正则表达式搜索文本的开始位置
  • .endpos:正则表达式搜索文本的结束位置

match对象的方法:

  • .group(0):匹配后的字符串(留坑:group(1)group(2)
  • .start():匹配字符串在原始字符串的开始位置
  • .end():匹配字符串在原始字符串的结束位置
  • span()(.start(), .end())

贪婪匹配&最小匹配:

Re库默认采用贪婪匹配,即输出匹配最长的子串。

如果要求得到最短的子串,需要对符号做如下修改:

  • *?:0次或多次扩展,取匹配的最小次数
  • +?:1次或多次扩展,取匹配的最小次数
  • ??:0次或1次扩展,取匹配的最小次数
  • {m, n}?:m次到n次扩展,取匹配的最小次数

两种写法:

  • 函数式写法:rst = re.search(r'...', '...')
  • 面向对象写法:pat = re.compile(r'...') rst = pat.search('...')

re.compile(r'...', flags = 0)可以将正则表达式的原生字符串形式编译成re对象,以上六种函数都可以直接用于re对象。

Selenium库

参考:

安装

pip install selenium

在https://chromedriver.storage.googleapis.com/index.html找到对应版本的chromedriver丢到chrome.exe所在文件夹。

(写代码的时候不要把文件命名为selenium.py!会出现ImportError: cannot import name webdriver

使用

大致框架

  • 预备:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome('C:\Program Files\Google\Chrome\Application\chromedriver.exe')

selenium.webdriver提供WebDriver的实现,Keys提供案件支持,如RETURNF1ALT

如果不给chromedriver.exe配置环境变量,就直接写绝对路径。

  • 加载网页:
driver.get("http://www.python.org")

……中间部分搞一些大新闻

  • 关闭网页(关闭一个标签页)
driver.close()

交互方式

如果想定位到一个可以输入的文本框,可以先在浏览器中检查网页的elements,找到对应位置的信息。

比如北航CAS登录页面的密码框的信息:

<input type="password" placeholder="请输入密码" i18n="login.form.password.placeholder" id="pwPassword" name="password">

可以这样定位:

elem = driver.find_element_by_id("pwPassword")

其它定位方式:

find_element_by_id
find_element_by_name
find_element_by_xpath #见下
find_element_by_link_text #见下
find_element_by_partial_link_text
find_element_by_tag_name #即查找HTML标签名
find_element_by_class_name #即查找class
find_element_by_css_selector #待填坑

(如果查找多个元素,改成elements即可,返回列表类型)

关于XPATH:

举例:

<html>
  <body>
       <form id="loginForm">
            <input name="username" type="text" />
			<input name="password" type="password" />
			<input name="continue" type="submit" value="Login" />
			<input name="continue" type="button" value="Clear" />
		</form>
	</body>
<html>

三种查找form的方法:

login_form = driver.find_element_by_xpath("/html/body/form[1]") #绝对路径
login_form = driver.find_element_by_xpath("//form[1]") #页面中第一个form元素
login_form = driver.find_element_by_xpath("//form[@id='loginForm']") #id为loginForm的form元素

三种查找username的方法:

username = driver.find_element_by_xpath("//form[input/@name='username']") #第一个form中name为username的input元素
username = driver.find_element_by_xpath("//form[@id='loginForm']/input[1]") #id为loginForm的form元素的第一个input元素
username = driver.find_element_by_xpath("//input[@name='username']") #第一个name属性是username的input元素

两种获取Clear按钮的方法:

clear_button = driver.find_element_by_xpath("//input[@name='continue'][@type='button']") #name是continue,type是button的input元素
clear_button = driver.find_element_by_xpath("//form[@id='loginForm']/input[4]") #id是loginForm的form元素的第四个input元素

关于通过链接文本获取超链接:

link = driver.find_element_by_link_text('Content')
link = driver.find_element_by_partial_link_text('PartialContent') #部分内容查找

模拟键盘:

elem.clear():将文本框清空

elem.send_keys("xxxxxxx"):输入

elem.send_keys(Keys.RETURN):回车

下拉选择框:

from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_name('name'))
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)

取消选择:

select = Select(driver.find_element_by_id('id'))
select.deselect_all()

点击按钮:

driver.find_element_by_id("submit").click()

弹出对话框:

alert = driver.switch_to_alert()
alert.accept()
alert.dismiss()
posted @ 2021-08-23 09:56  Hany01  阅读(227)  评论(0编辑  收藏  举报