爬虫基础

本文深入探讨网络爬虫技术,涵盖requests库的GET与POST请求、cookies与headers的使用,以及session对象管理。详细讲解XPath语法,lxml库解析HTML,结合XPath提取数据。介绍正则表达式语法,re模块的高级应用。演示BeautifulSoup解析HTML,提取标签与属性。此外,还介绍了Selenium自动化浏览器操作,处理动态页面,以及Cookie和页面等待技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

requests库

import requests

#get请求及常用参数
#status_code 返回码
#reason 响应结果
#text  响应内容
#json() json响应内容
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'}
cookies = {'username': 'duson', 'password': 'duson0.0'}
method_get = requests.get('http://httpbin.org/get', params={'a':'1', 'b':'2'}, headers=headers, cookies=cookies)
method_post = requests.post('http://httpbin.org/post', data={'aa':'1', 'bb':'2'}, params={'a':'1', 'b':'2'}, headers=headers, cookies=cookies)
#print(method_get.status_code, method_get.reason, method_get.text)
print('get请求', method_get.json())
print('post请求', method_post.json())

#使用requests.Session()对象请求
#创建一个Session对象
rs = requests.Session()
#session对象会保存服务器返回的set-cookies头信息内的内容
rs.get('http://httpbin.org/cookies/set/userid/12345678')
rs.get('http://httpbin.org/cookies/set/token/xxxxxxxx')
#下一次请求会将s本地所有r的cookies信息自动添加到请求头信息
r = rs.get('http://httpbin.org/cookies')
print('检查session中的cookies',r.json())

#在requests中使用代理
print('不使用代理', requests.get('http://httpbin.org/ip').json())
print('使用代理', requests.get('http://httpbin.org/ip', proxies = {
    'http': 'http://120.24.189.164:41801'
}).json())

 

XPath语法:

使用方式:

使用//获取整个页面中的元素,然后写标签名,然后再写谓词进行提取

//div[@class="abc"]

谓语: 

路径表达式描述
//div/a[1]选择div下的第一个a标签
//div/a[last()]选择div下的倒数第一个a标签
//div/a[position()<3]选择div下的前面两个a标签
//div[contains(@class,'abc')]选择div中带有class=abc的标签
//div[@class]选择所有带class属性的标签
//div[@class="abc"]选择所有带class属性并且值为abc的标签
//div[@*]*为通配符意为获取所有
//div[@class="abc"] | //div[@class="def"]|或,用于选择多个路径
//div[@class="abc" and @id="def"]and 且,or或
//a/@href获取所有a标签的href的值
//a/text()获取所有a标签的文本
//a/[not(@class)]获取不包含class的a标签
//a/[not(@class) and not(@id)]获取不包含class且不包含id的a标签
//a/[not(contains(@class,'expire'))]获取不包含class="expire"的a标签

需要注意的知识点:

1,//标签名[contains(@属性名,"属性值")]:有时候某个属性中含了多个值,可使用contains进行提取

<div class="abc def"></div>
//div[contains(@class,'abc')]

2,谓词中的下标是从1开始而不是0

lxml库

安装:pip install lxml

基本使用:

用于解析html代码,并且在解析html代码的时候,如果html代码不规范,会自动补全

1.通过requests库爬下来的数据的解释

from lxml import etree

text = '''
<div class="s-menus-outer">
	<div id="s_menus_wrapper" class="menus-wrapper"><span class="s-menu-item s-opacity-white-background current" data-id="2">
			推荐 </span><span class="s-menu-item s-opacity-white-background" data-id="1"> 导航 </span></div>
	<div class="s-bg-space s-opacity-white-background"></div><span class="s-menu-music" data-id="3"></span>
</div>
'''

#利用etree.HTML,将字符串解析为HTML文档
html = etree.HTML(text)

#按字符串序列化HTML文档
#tostring解释出来的如果是byte类型的字符串则需要添加encoding指定编码后用decode解码,方便查看
result = etree.tostring(html,encoding='utf-8').decode('utf-8')

print(result)

2.解释文件中的html代码

from lxml import etree

html = etree.parse('text.html')

#按字符串序列化HTML文档
#tostring解释出来的如果是byte类型的字符串则需要添加encoding指定编码后用decode解码,方便查看
result = etree.tostring(html,encoding='utf-8').decode('utf-8')

print(result)

3.解释文件中的html代码时默认是xml解析器,html出现标签不完整和开始结束标签不匹配时需要自己指定解析器修复

from lxml import etree

#定义html解析器
parser = etree.HTMLParser(encoding='utf-8')

#etree.parse第二个参数为指定解析器
html = etree.parse('text.html',parser=parser)

result = etree.tostring(html,encoding='utf-8').decode('utf-8')

print(result)

lxml结合xpath注意事项:

1.使用xpath语法,element.xpath返回的是一个列表

import lxml from etree

parser = etree.HTMLParser(encoding='utf-8')
htmlElement = etree.parse('test.html',parser=parser)

tags = htmlElement.xpath('//div')
from urllib.parse import urlparse
import os
from lxml import etree
import requests

requ = requests.get('http://www.xiachufang.com/')
#定义html解析器
requestTest = etree.HTML(requ.text)
imgs = requestTest.xpath('//img')
#创建文件夹
'''
os.path.join(path1[, path2[, ...]])	    把目录和文件名合成一个路径
os.path.isdir(path)	                    判断路径是否为目录
os.path.dirname(path)	                返回文件的路径不算文件名
'''
image_dir = os.path.join(os.curdir,'images')
if not os.path.isdir(image_dir):
    os.mkdir(image_dir)
urls = []
for v in imgs[::-1]:
    url = ''
    if v.xpath('@data-src'):
        url = v.xpath('@data-src')[0].split('@')[0]
    else:
        url = v.xpath('@src')[0].split('@')[0]
    o = urlparse(url)
    filename = o.path[1:]
    if filename: #判断是否存在文件,防止因不存在文件名而错误
        filepath = os.path.join(image_dir,filename)  #即将保存的完整路径
        if not os.path.isdir(os.path.dirname(filepath)):    #防止文件有子目录
            os.mkdir(os.path.dirname(filepath))             #创建目录
        res = requests.get(url)                             #请求文件
        with open(filepath,'wb') as f:
            for c in res.iter_content(1024):                #循环进制内容,每次写入1m
                f.write(c)



2.获取某个标签的属性的值:

href = htmlElement.xpath("//a/@href")

3.获取标签内的文本,xpath内添加"."代表在获取当前标签下的标签

text = htmlElement.xpath("./td[2]/text()")[0]

beautifulSoup

4个常用的对象:Tag,NavigatableString,BeautifulSoup,Comment

find和find_all和select

from bs4 import BeaudifulSoup
#标签太多,省略一万个
html = '''
<ul>
    <li id="bs4liid1" class="bs4li">
        <a href="baidu.com">百度</a>
    </li>
    <li id="bs4liid2" class="bs4li">
        <a href="qq.com">腾讯</a>
    </li>
    <li id="bs4liid3" class="bs4li">
        <a href="alibaba.com">阿里</a>
    </li>
</ul>
'''
soup = BeaudifulSoup(html,'lxml')
#find获取第一个符合条件的标签
li1 = soup.find('li',id='bs4liid1')
li2 = soup.find('li',attrs={'id':'bs4liid2'})
li3 = sooup.select_one('li#bs4liid1')
#find_all获取所有符合条件的标签
lis1 = soup.find_all('li',class_='bs4li',limit=3) #limist指定提取多少个
lis2 = soup.find_all('li',attrs={'class':'bs4li'})
lis3 = soup.select('li.bs4li',limit=3) #select支持css选择器语法,limist指定提取多少个
#获取属性
aList = soup.find_all('a')
for a in aList:
    href1 = a['href']
    href2 = a.attrs['href']
#提取文本,string,strings,stripped_strings,get_text
#string:获取某个标签下的非标签字符串,返回字符串
#strings:获取甘个标签下的子孙标签下的非标签字符串,返回列表生成器
#stripped_strings:获取某个标签下的子孙标签下的非标签字符串,会去掉空白字符,返回列表生成器
#get_text:获取某个标签下的子孙非标签字符串,返回普通字符串而不是列表

正则表达式

语法说明表达式完整匹配的字符
字符
.匹配任意除换行符“\n”外的字符,re.DOTALL模式下也可匹配\na.cabc
\转义字符,用于\*?+.^|......a\.ca.c
[]字符集,用于匹配范围,第一个字符是^则表示取反a[a-zA-Z]caac,azc,aAc,aZc
预定义字符集,可写在[]中
\d匹配0-9的数字a\dca1c,a9c
\D匹配非0-9的字符  [^0-9]a\Dcabc,azc,aAc,aZc
\w单词0-9,a-z,A-Z,_a\wca0c,a9c,aac,azc,aAc,aZc
\W非的0-9,a-z,A-Z,_单词  [^\w]a\Wca@c,a c
\s

匹配空白字符包括\n,\t,\r,\f,\v,空格

a\sca c
\S

匹配非空白字符 [^\s]

a\Scabc
\u4E00-\u9FA5匹配中文文字a哈a
数量词,用在字符或()后
匹配前一个字符0或1次或取消贪婪模式abc?ab,abc
+匹配前一个字符1或无限次abc+abc,abcc.abccc
*匹配前一个字符0或无限次abc*ab,abc,abcccc
{m}匹配前一个字符m次abc{3}abccc
{m,n}匹配前一个字符m到n次,省略m为0到n次,省略n为m到无限次abc{1,3}abc.abcc.abccc
??,+?,*?,{m,n}?例* + ? {m,n}变成非贪梦模式  
逻辑,分组
|代表左右表达式任意匹配一个abc|defabc,def
()分组  
边界匹配(不消耗待匹配字符串中的字符)
^匹配字符串开头,在多行模式中匹配每一行的开头^abcabc
$匹配字符串末尾,在多行模式中匹配每一行的末尾$abcabc
\A仅匹配字符串开头\Aabcabc
\Z仅匹配字符串末尾abc\Zabc
\b匹配\w和\W之间a\b!bca!bc
\B[^\b]a\Bbcabc
特殊构造,不作为分组
(?=...)之后的字符串内容需要匹配表达式才能成功匹配,不消耗字符串a(?=\d)后面是数字的a
(?!...)之后的字符串内容需要不匹配表达式才能成功匹配,不消耗字符串a(?!\d)后面不是数字的a
(?<=...)之前的字符串内容需要匹配表达式才能成功匹配,不消耗字符串(?<=]d)a前面是数字的a
(?<!...)之前的字符串内容需要匹配表达式才能成功匹配,不消耗字符串(?<!]d)a前面不是数字的a

Python 的 re 模块

常用函数,compile,match,search,findall,finditer,split,sub

  • match 方法:从起始位置开始查找,一次匹配
  • search 方法:从任何位置开始查找,一次匹配
  • findall 方法:全部匹配,返回列表
  • finditer 方法:全部匹配,返回迭代器
  • split 方法:分割字符串,返回列表
  • sub 方法:替换字符串

re.DOTALL模式,match,search,findall,finditer

re 模块的一般使用步骤如下:

  1. 使用 compile() 函数将正则表达式的字符串形式编译为一个 Pattern 对象

  2. 通过 Pattern 对象提供的一系列方法对文本进行匹配查找,获得匹配结果,一个 Match 对象。

  3. 最后使用 Match 对象提供的属性和方法获得信息,根据需要进行其他的操作

match方法:match(string, start, end)

import re
pattern = re.compile(r'\d+')
m1 = pattern.match('one12twothree34four')  # 查找头部,没有匹配
m2 = pattern.match('one12twothree34four',2,10)  # 从e开始匹配,匹配失败
m3 = pattern.match('one12twothree34four',3,10)  # 从1开始匹配,匹配成功
m3.group(0)  # 0可省略 打印结果为12
m3.start(0)  # 0可省略 打印结果为3
m3.end(0)    # 0可省略 打印结果为5
m3.span(0)   # 0可省略 打印结果为(3,5)

在上面,当匹配成功时返回一个 Match 对象,其中:

  • group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);

  • start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;

  • end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
  • span([group]) 方法返回 (start(group), end(group))。

search 方法:search(string, start, end)

search 方法用于查找字符串的任何位置,它也是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果,它的一般使用形式如下:

search(string[, pos[, endpos]])

string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。

当匹配成功时,返回一个 Match 对象,如果没有匹配上,则返回 None。

import re
pattern = re.compile('\d+')
m = pattern.search('one12twothree34four')  # 这里如果使用 match 方法则不匹配
m
<_sre.SRE_Match object at 0x10cc03ac0>
m.group()
'12'
m = pattern.search('one12twothree34four', 10, 30)  # 指定字符串区间
m
<_sre.SRE_Match object at 0x10cc03b28>
m.group()
'34'
m.span()
(13, 15)

findall 方法

获得所有匹配的结果。

findall 方法的使用形式如下:

findall(string[, pos[, endpos]])

string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。

findall 以列表形式返回全部能匹配的子串,如果没有匹配,则返回一个空列表。

import re
pattern = re.compile(r'\d+')   # 查找数字

result1 = pattern.findall('hello 123456 789')
result2 = pattern.findall('one1two2three3four4', 0, 10)

print(result1) # ['123456', '789']
print(result2) # ['1', '2']

finditer 方法

finditer 方法的行为跟 findall 的行为类似,也是搜索整个字符串,获得所有匹配的结果。但它返回一个顺序访问每一个匹配结果(Match 对象)的迭代器。

import re
pattern = re.compile(r'\d+')

result_iter1 = pattern.finditer('hello 123456 789')
result_iter2 = pattern.finditer('one1two2three3four4', 0, 10)

print(type(result_iter1)
print(type(result_iter2)

for m1 in result_iter1:   # m1 是 Match 对象
    print('matching string: {}, position: {}'.format(m1.group(), m1.span()))

for m2 in result_iter2:
    print('matching string: {}, position: {}'.format(m2.group(), m2.span()))

split 方法

split 方法按照能够匹配的子串将字符串分割后返回列表

split(string[, maxsplit])

maxsplit 用于指定最大分割次数,不指定将全部分割。

看看例子:

import re
p = re.compile(r'[\s\,\;]+')
print(p.split('a,b;; c   d'))

执行结果:

['a', 'b', 'c', 'd']

sub 方法

sub 方法用于替换字符串

sub(repl, string[, count])

repl 可以是字符串也可以是一个函数:

  • 如果 repl 是字符串,则会使用 repl 去替换字符串每一个匹配的子串,并返回替换后的字符串,另外,repl 还可以使用 id 的形式来引用分组,但不能使用编号 0;

  • 如果 repl 是函数,这个方法应当只接受一个参数(Match 对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。

  • count 用于指定最多替换次数,不指定时全部替换。
import re
p = re.compile(r'(\w+) (\w+)') # \w = [A-Za-z0-9]
s = 'hello 123, hello 456'

print(p.sub(r'hello world', s))  # 使用 'hello world' 替换 'hello 123' 和 'hello 456'
print(p.sub(r'\2 \1', s))        # 引用分组

def func(m):
    return 'hi' + ' ' + m.group(2)

print(p.sub(func, s))
print(p.sub(func, s, 1))         # 最多替换一次

执行结果:

hello world, hello world
123 hello, 456 hello
hi 123, hi 456
hi 123, hello 456

 

匹配中文

在某些情况下,我们想匹配文本中的汉字,有一点需要注意的是,中文的 unicode 编码范围 主要在 [u4e00-u9fa5],这里说主要是因为这个范围并不完整,比如没有包括全角(中文)标点,不过,在大部分情况下,应该是够用的。

假设现在想把字符串 title = u'你好,hello,世界' 中的中文提取出来,可以这么做:

import re

title = u'你好,hello,世界'
pattern = re.compile(ur'[\u4e00-\u9fa5]+')
result = pattern.findall(title)

print(result)

注意到,我们在正则表达式前面加上了两个前缀 ur,其中 r 表示使用原始字符串,u 表示是 unicode 字符串。

执行结果:

[u'\u4f60\u597d', u'\u4e16\u754c']

注意:贪婪模式与非贪婪模式

  1. 贪婪模式:在整个表达式匹配成功的前提下,尽可能多的匹配 ( * );
  2. 非贪婪模式:在整个表达式匹配成功的前提下,尽可能少的匹配 ( ? );
  3. Python里数量词默认是贪婪的。

示例一 : 源字符串:abbbc

  • 使用贪婪的数量词的正则表达式 ab* ,匹配结果: abbb。

    * 决定了尽可能多匹配 b,所以a后面所有的 b 都出现了。

  • 使用非贪婪的数量词的正则表达式ab*?,匹配结果: a。

    即使前面有 *,但是 ? 决定了尽可能少匹配 b,所以没有 b。

示例二 : 源字符串:aa<div>test1</div>bb<div>test2</div>cc

  • 使用贪婪的数量词的正则表达式:<div>.*</div>

  • 匹配结果:<div>test1</div>bb<div>test2</div>

这里采用的是贪婪模式。在匹配到第一个“</div>”时已经可以使整个表达式匹配成功,但是由于采用的是贪婪模式,所以仍然要向右尝试匹配,查看是否还有更长的可以成功匹配的子串。匹配到第二个“</div>”后,向右再没有可以成功匹配的子串,匹配结束,匹配结果为“<div>test1</div>bb<div>test2</div>


  • 使用非贪婪的数量词的正则表达式:<div>.*?</div>

  • 匹配结果:<div>test1</div>

正则表达式二采用的是非贪婪模式,在匹配到第一个“</div>”时使整个表达式匹配成功,由于采用的是非贪婪模式,所以结束匹配,不再向右尝试,匹配结果为“<div>test1</div>”。

json读写

  1. dump()  将python对象写入文件
  2. dumps() 将python对象转换成json
  3. load(),
  4. loads()

dump()、dumps()

import json

person= [
    {'name':'张三','age':20,'height':180},
    {'name':'李四','age':21,'height':170},
    {'name':'王五','age':22,'height':160}
]
# dumps函数将python对象转换为json字符串
json_str = json.dumps(person)
# dump把json写入文件
with open('person.json','w',encoding='utf-8') as fp:
    #json在dump的时候默认存放ascii字符,把ensure_ascii=False后正常保存中文
    json.dump(person,fp,ensure_ascii=False)

load()、loads()

import json

json_str = '[{"name":"张三","age":20},{"name":"李四","age":21},{"name":"王五","age":22}]'
person1 = json.loads(json_str)
print(person1)

width open('person.json','r',encoding='utf-8') as fp:
    person2 = json.load(fp)
    print(person2)
    for person in person2:
        print(person)

cvs文件读写

  1. reader()          以列表形式读取
  2. DictReader()  以字典形式读取
  3. writer()           以列表形式写入
  4. DictWriter()    以字典形式写入

reader()、DictReader()

import csv

def list_read_csv():
    with open('stock.csv', 'r') as fp:
        #返回结果reader是一个迭代器
        reader = csv.reader(fp)
        # 每执行一次next方法,reader就会跳一行
        next(reader)
        for x in reader:
            print(x)

def dict_read_csv():
    with open('stock.csv', 'r') as fp:
        #使用DictReader创建的reader对象不会包含标题那行的数据,返回结果是个迭代器
        reader = csv.DictReader(fp)
        for x in reader:
            print(x)
        

writer()、DictWriter()

import csv
headers = ['name','age','height']
values = [('张三',20,'180'),('李四',21,'170'),('王五',22,'160')]
# 写入csv文件时默认每一行会插入一条空行,newline=''去掉空行
with open('person1.cvx','w',encoding='utf-8',newline='') as fp:
    writer = csv.writer(fp)
    # 写入表头,writerow写入一行,writerows写入多行
    writer.writerow(headers)
    writer.writerows(values)
values2 = [
    {'name':'张三','age':20,'height':'180'},
    {'name':'李四','age':21,'height':'170'},
    {'name':'王五','age':22,'height':'160'}
]
with open('persons2.cvs','w',newline='',encoding='utf-8') as fp:
    # DictWriter需要先传入表头,然后执行writeheader写入表头
    writer = csv.DictWriter(fp,headers)
    writer.writeheader()
    writer.writerows(values2)

seleninum + chromedriver获取动态数据

根据电脑上的chrome浏览版本下载,下载地址:http://chromedriver.storage.googleapis.com/index.html

安装配置

  1. 安装selenium   pip install selenium
  2. 安装chromedriver    把chromedriver.exe放到不需要权限的纯英文目录下
from selenium import webdriver
#chromedriver的绝对路径
driver_path = r"D:\Anaconda3\Scripts\chromedriver.exe"
#初始化一个driver,并指定chromedriver的路径
driver = webdriver.Chrome(executable_path=driver_path)
#请求网页
driver.get("https://www.baidu.com")
#通过page_source获取网页源代码
print(driver.page_source)
#打印当前driver页面url
print(driver.current_url)

#关闭当前页面
#driver.close()
#关闭整个浏览器
#driver.quit()

定位元素

#find_element_by_id : 根据id来查找某个元素
tag1 = driver.find_element_by_id('name')

#find_element_by_class_name : 根据类名查找元素,find_elements_by_class_name获取所有
tag2 = driver.find_element_by_class_name('name')

#find_element_by_name : 根据name属性的值来查找元素,find_elements_by_name获取所有
tag3 = driver.find_element_by_name('value')

#find_element_by_tag_name : 根据标签名来查找元素,find_elements_by_tag_name获取所有
tag4 = driver.find_element_by_tag_name('div')

#find_element_by_css_selector: 根据css选择器选择元素,find_elements_by_css_selector获取所有
tag5 = driver.find_element_by_css_selector('.className > childrenName')

#find_element_by_xpath: 根据xpath方法来获取元素
tag6 = driver.find_element_by_xpath('//div')

操作表单元素

1、操作输入框,文本框

inputTag = driver.find_element_by_id('inp')
#对输入框填充数据
inputTag.send_keys('python')
#清空输入框内容
inputTag.clear()

2、操作checkbox,radio用法相同

box = driver.find_element_by_name('boxName')
box.click()

3、操作select

from selenium.webdriver.support.ui import Select
#选择select标签,然后使用Select()创建对象
selectTag = Select(driver.find_element_by_tag_name('select'))
#通过下标选择
selectTag.select_by_index(1)
#通过value选择
selectTag.select_by_value
#通过可视文本选择
selectTag.select_by_visible_text('文本值')
#取消所有选中项
selectTag.deselect_all()

行为链(多用于自动化测试)

通过行为链类ActionChains完成一系列动作

from selenium.webdriver.common.action_chains import ActionChains

inputTag = driver.find_element_by_id('kw')
subitTag = driver.fiind_element_by_id('su')
#创建对象
actions = ActionChains(driver)
#移动鼠标到对应标签
actions.move_to_element(inputTag)
#对input框输入值
actions.send_keys_to_element(inputTag,'python')
#移动鼠标到提交按钮
actions.move_to_element(submitTag)
#点击按钮
actions.click(submitTag)
actions.perform()

#更多操作 文档:https://selenium-python.readthedocs.io/api.html

Cookie操作

#获取所有cookie
for cookie in driver.get_cookies():
    print(cookie)

#根据key获取cookie(key)
value = driver.get_cookie(key)

#删除所有cookie
driver.delete_all_cookies()

#删除某个cookie
driver.delete_cookie(key)

页面等待

用于解决因ajax加载页面导致dom元素未加载所产生的错误,一隐式等待,二显式等待

1、隐式等待:调用driver.implicitly_wait,等10秒后再获取元素

driver = webdriver.Chrome(executable_path=driver_path)
driver.implicitly_wait(10)
driver.get("https://www.baidu.com/")

2、显示等待:根据某个条件成立后才执行获取元素的操作。也可以指定一个最大等待时间,如果超这个时间就抛出异常

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver_path = r"D:\Anaconda3\Scripts\chromedriver.exe"
driver = webdriver.Chrome(executable_path=driver_path)
driver.get("https://www.douban.com/")

element = WebDriverWait(driver,30).until(
    EC.presence_of_element_located((By.TAG_NAME,'iframe'))
)
# frame()查找和定位iframe框架的方法(switch_to)
driver.switch_to.frame(driver.find_element_by_tag_name('iframe'))
driver.find_element_by_class_name('account-tab-account').click()

username = WebDriverWait(driver, 10).until(lambda driver: driver.find_element_by_css_selector('#username'))
pwd = WebDriverWait(driver, 10).until(lambda driver: driver.find_element_by_css_selector('#password'))
username.send_keys('373423271@qq.com')
pwd.send_keys('duson0.0')

3、一些其他的等条件

  • presence_of_element_located:某个元素已经加载完毕
  • presence_of_all_element_located:网页中所有满足条件的元素都加载完毕
  • element_to_be_cliable:某个元素可以点击了
  • 更多条件参考地址:http://selenium-python.readthedocs.io/waits.html

切换页面

注:打开新窗口后需要通过window_handles获取窗口列表,再用switch_to.window()切换页面,否则页面不变

#excute_script执行js代码,使用js代码打开新窗口
driver.execute_script('window.open("http://www.duban.com")')
#切换到新页面,window_handles获取页面
driver.switch_to.window(driver.window_handles[1])

print(driver.window_handles)
print(driver.current_url)
print(driver.page_source)

设置代理ip

使用代理ip防止爬虫被封

from selenium import webdriver
#创建options对象
options = webdriver.ChromeOptions()
#添加代理配置
options.add_argument("--proxy-server=http://61.164.39.68:53281")
driver_path = r"D:\Anaconda3\Scripts\chromedriver.exe"
#通过options参数传入
driver = webdriver.Chrome(executable_path=driver_path,options=options)
driver.get("http://httpbin.org/ip")

WebElement元素

from selenium.webdriver.remote.webelement import WebElement类是每个获取出来的元素的所属类

有一些常用属性:

  1. 1.get_attribute :获取某个标签的某个属性值
  2. 2. screentshot:获取当前页面的截图。这个方法只能在driver上用
  3. 3.driver的对象类,也是继承自WebElement类

其他方法可查看源代码

from selenium import webdriver

driver_path = r"D:\Anaconda3\Scripts\chromedriver.exe"
driver = webdriver.Chrome(executable_path=driver_path)
driver.get("https://www.baidu.com/")

submitBtn = driver.find_element_by_id('su')
driver.save_screenshot('baidu.png')
print(type(submitBtn))
print(submitBtn.get_attribute("value"))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值