Python爬虫之利用xpath爬取ip代理网站的代理ip

本文介绍了Python中requests库的使用,包括HTTP请求、响应状态码和编码处理。接着讲解了XPath在XML和HTML文档中的应用,以及lxml库的安装和基本操作。通过实例展示了如何利用XPath选择特定节点和属性。最后,演示了一个爬取IP代理网站的示例,包括处理编码问题、提取IP和筛选有效代理的过程,以及如何爬取多页数据。
摘要由CSDN通过智能技术生成

爬虫工具

python3 pycharm edge/chrome

requests库的用法

requests库是python中简单易用的HTTP库
用命令行安装第三方库 pip install requests
导入库import requests
获取响应内容

import requests
r = requests.get('http://www.baidu.com/')
print("文本编码:", r.encoding)  # ISO-8859-1
print("响应状态码:", r.status_code)
# print ("字符串方式的响应体:", r.text)
# 响应体乱码解决
print("字符串方式的响应体:", r.text.encode('ISO-8859-1'))
xpath的用法

xpath可以在XML文档中查找信息,在XML中通过元素和属性进行定位
常用的表达式

表达式描述
nodename选取此节点的所有子节点
/从根节点选取(取子节点)。
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
.选取当前节点
选取当前节点的父节点
@选取属性

谓语

路径表达式
//table/tbody/trtable标签下的tbody标签下的所有tr节点
//a/@src选取a标签下的src属性
//div[@class=“box”]选取class="box"的div节点
使用lxml解析

安装pip install lxml
导入库from lxml import etree
lxml将_html_文本转换为_xml_对象
实例化一个**etree**对象,且将解析的源码加载到该对象中

tree = etree.HTML(html)
# result = etree.tostring(tree) 补全html的基本写法
#                               比如补全缺少的结束标签   
xpath中的 text(), string(), data()的区别如下:
  • text()仅仅返回所指元素的文本内容
  • string()函数会得到所指元素的所有节点文本内容,这些文本会被拼接成一个字符串.
  • data()大多数时候和string()通用不建议经常使用.(可能会影响性能)
基本使用
from lxml import etree
wb_data = """
        <div>
            <ul>
                 <li class="item-0"><a href="link1.html">first item</a></li>
                 <li class="item-1"><a href="link2.html">second item</a></li>
                 <li class="item-inactive"><a href="link3.html">third item</a></li>
                 <li class="item-1"><a href="link4.html">fourth item</a></li>
                 <li class="item-0"><a href="link5.html">fifth item</a>
             </ul>
         </div>
        """
html = etree.HTML(wb_data)
print(html)
result = etree.tostring(html)
print(result.decode("utf-8"))

输出

<Element html at 0x1cf63c799c8>
<html><body><div>
            <ul>
                 <li class="item-0"><a href="link1.html">first item</a></li>
                 <li class="item-1"><a href="link2.html">second item</a></li>
                 <li class="item-inactive"><a href="link3.html">third item</a></li>
                 <li class="item-1"><a href="link4.html">fourth item</a></li>
                 <li class="item-0"><a href="link5.html">fifth item</a>
             </li></ul>
         </div>
        </body></html>
.text/text()获取某个标签内容
# html = etree.HTML(wb_data)
# html_data = html.xpath('/html/body/div/ul/li/a')
# for i in html_data:
#    print(i.text)
    
html_data = html.xpath('/html/body/div/ul/li/a/@href')
# 或者 html_data = html.xpath('//li/a//@href')
for i in html_data:
    print(i)

爬取ip网站

简单爬取ip
对ip代理网站ip3366.net发起网络请求
import requests  # 不要忘记导入库
from lxml import etree

url = 'http://www.ip3366.net/'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36'
}  # headers是解决requests请求反爬的方法之一,伪装成浏览器
response = requests.get(url, headers=headers)
print(response.text)

发现是乱码,我们可以用print(response.encoding)打印出这个网站的编码是ISO-8859-1,所以我们用encode('_编码方式_')将我们爬取到的HTML改成这个编码

page_text = response.text.encode('ISO-8859-1')

创建etree实例对象用于解析HTML源码,并找到定位ip节点的位置

page_text = response.text.encode('ISO-8859-1')
tree = etree.HTML(page_text)
tr_list = tree.xpath('//*[@id="list"]/table/tbody/tr')  # tr的XML的列表
print(tr_list)
ip_list = []
for tr in tr_list:
    ip = tr.xpath('./td')[0].text + ':' + tr.xpath('./td')[1].text
	# 通过HTML源码看出ip和port的在td的第一个和第二个所以定位索引0,1的文本
	ip_list.append(ip)  #list.append(x) 将x加入list尾
print(ip_list)

输出:

[<Element tr at 0x1f887077d40>, <Element tr at 0x1f887077d00>, <Element tr at 0x1f887077cc0>, <Element tr at 0x1f887057e80>, <Element tr at 0x1f887057f80>, <Element tr at 0x1f8870a3800>, <Element tr at 0x1f8870a3d40>, <Element tr at 0x1f8870a3880>, <Element tr at 0x1f88709ac80>, <Element tr at 0x1f8870a3a00>]
['113.252.11.250:8118', '103.143.196.50:8080', '115.218.4.39:9000', '27.159.188.239:3256', '115.218.0.13:9000', '118.114.110.231:8060', '103.82.170.211:808', '27.159.188.243:3256', '115.218.1.249:9000', '106.14.244.92:8080']

完整代码

# -*- coding = utf-8 -*-  默认utf-8的编码

import requests
from lxml import etree
url = 'http://www.ip3366.net/'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36'
}  # headers是解决requests请求反爬的方法之一,伪装成浏览器
response = requests.get(url, headers=headers)
page_text = response.text.encode('ISO-8859-1')
tree = etree.HTML(page_text)
tr_list = tree.xpath('//*[@id="list"]/table/tbody/tr')  # tr的XML列表
print(tr_list)
ip_list = []
for tr in tr_list:
    ip = tr.xpath('./td')[0].text + ':' + tr.xpath('./td')[1].text
    ip_list.append(ip)
print(ip_list)
筛选ip

-我们向一个正常网站发起请求测试ip是否可用,不可用就在列表中删除
(我这个移除方法可能效率很低)

for i in ip_list:
    try:
        r = requests.get('http://2021.ip138.com/', headers=headers, proxies={"http": i}, timeout=2)
        if r.status_code == 200:
            pass
        else:
            ip_list.remove(i)
    except:
        ip_list.remove(i)

-我们从网站页面和HTML源码可以看出网站提供了每个代理ip的响应速度,我可以在存ip代理之前判断ip的响应速度再存。

        for tr in tr_list:
            tr_time = tr.xpath('./td')[6].text
            tr_time = tr_time.replace('秒', '')
            if float(tr_time) <= 2:
                ip = tr.xpath('./td')[0].text + ':' + tr.xpath('./td')[1].text
                ip_list.append(ip)
爬取多个页面

[http://www.ip3366.net/?stype=1&page=1](http://www.ip3366.net/?stype=1&page=1)第一页
[http://www.ip3366.net/?stype=1&page=2](http://www.ip3366.net/?stype=1&page=2)第二页
[http://www.ip3366.net/?stype=1&page=5](http://www.ip3366.net/?stype=1&page=5)第五页
通过观察每一页的网址我们可以发现传的page值就是页数的值
所以我们可以根据这个规律爬取多个网站

    for page in range(1, 5):
        url = 'http://www.ip3366.net/?page={}'.format(page)
        response = requests.get(url, headers=headers)

完整的代码:

import requests
from lxml import etree

def get_ip():
    ip_list = []
    tr_list = []
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36'
    }
    for page in range(1, 5):
        url = 'http://www.ip3366.net/?page={}'.format(page)
        response = requests.get(url, headers=headers)
        page_text = response.text.encode('ISO-8859-1')
        tree = etree.HTML(page_text)
        tr_list = tree.xpath('//*[@id="list"]/table/tbody/tr')



        for tr in tr_list:
            tr_time = tr.xpath('./td')[6].text
            tr_time = tr_time.replace('秒', '')
            if float(tr_time) <= 2:
                ip = tr.xpath('./td')[0].text + ':' + tr.xpath('./td')[1].text
                ip_list.append(ip)

    for i in ip_list:
        try:
            r = requests.get('http://2021.ip138.com/', headers=headers, proxies={"http": i}, timeout=2)
            if r.status_code == 200:
                pass
            else:
                ip_list.remove(i)
        except:
            ip_list.remove(i)
            
    print(ip_list)
    
if __name__ == '__main__':
    get_ip()
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值