爬虫之urllib库的使用


1. 前言

urllib库是python中最常用的库之一,在Python2中,有urllib和urllib2两个库来实现请求的发送,而在Python3中,统一为了urllib,其官方文档链接为:https://docs.python.org/3/library/urllib.html。urllib是Python内置的HTTP请求库,urllib对于爬虫爱好者来说非常的友好,这个库主要是用来获取数据的,具体使用方法如下所示:

视频讲解urllib库


2. urllib库使用

urllib库用于操作网页 URL,并对网页的内容进行抓取处理 ,urllib库是python自带的库,在urllib库中有如下的模块:

  1. urllib.request - 打开和读取 URL。
  2. urllib.error - 包含 urllib.request 抛出的异常。
  3. urllib.parse - 解析 URL。
  4. urllib.robotparser - 解析 robots.txt 文件

1.urllib.request模块的使用

1.1 urllib.request模块基本使用

访问一个页面,一般分为如下四步

  1. 定义一个url 就是你要访问的地址
  2. 模拟浏览器向服务器发送请求 response响应
  3. 获取响应中的页面的源码
  4. 打印数据

urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,cadefault=False,context=None):使用urlopen( )函数可以发送一个请求,urlopen( )函数的完整参数列表如左所示:

  • url参数用于指定要请求的URL路径
  • data参数可以设置请求要传递的参数,使用时需要使用bytes( )方法将参数转化为字节流编码格式的内容,即bytes类型;并且如果 使用了data参数,则请求方法就不再是GET方法了,而是POST方法。
  • timeout参数可以设置超时时间,单位为秒,如果请求超过了设置的超时时间还没有得到响应,就会抛出异常。如果不指定timeout参 数,就会使用全局默认时间。它支持HTTP、HTTPS、FTP请求
  • context参数,它必须是ssl.SSLContext类型,用来制定SSL设置。此外,cafile和capath这两 个参数分别指定CA证书的和它的路径,这个在请求HTTPS链接时会有用,cadefault参数已经启用了,其默认值为false。
import urllib.request  # 导入模块

url = "http://www.baidu.com" 
respose = urllib.request.urlopen(url)  # 在urllib.request模块中,有urlopen()函数,这个函数返回一个对象,这个对象又有很多方法,常用的有6个方法

# print(respose)  <http.client.HTTPResponse object at 0x000001EE54317880>

contents = respose.read().decode('utf-8')
# read方法  返回的是字节形式的二进制数据
print(contents)

contents = respose.read().decode('utf-8'),当我们访问页面时,页面把字母编码成字节,所以respose.read()获取的是字节,我们要把字节变成字母就要进行编码,所以进行utf-8编码

1.2urllib.request模块的对象和方法
  1. 一个对象

    import urllib.request  # 导入模块
    
    url = "http://www.baidu.com" 
    respose = urllib.request.urlopen(url)  #  response对象,这个对象又有很多方法,常用的有6个方法
    
  2. 6个方法

    • read(num):num不写时,获取所有的数据,num写时,获取num个字节的数据
    • readline():获取一行数据
    • readlines():以列表的形式获取所有的数据
    • getcode():获取状态码
    • geturl():获取地址
    • getheads():获取头部信息
    import urllib.request
    
    url = "http://www.baidu.com"
    respose = urllib.request.urlopen(url)
    
    # contents = respose.read()  # 读取全部
    # contents = respose.read(5)  # 读取5个字节
    # contents = respose.readline()  # 读取一行
    # contents = respose.readlines()  # 一行一行的显示
    
    # 返回状态码  如果是200了 那么就证明我们的逻辑没有错
    # print(response.getcode())
    
    # 获取是一个状态信息
    # print(response.getheaders())
    
    # 返回的是url地址
    # print(response.geturl())
    print(contents)
    
  3. 6个属性

msg、version、status、reason、debuglevel、closed等

1.3 urllib.request模块下载

下载功能使用的方法是urlretrieve(url,filename),该方法的第一个参数是下载的地址,第二个参数是下载后的名称,后缀名一定要写对

  1. 下载网页 (http://www.baidu.com)
  2. 下载图片 (https://cn.bing.com/images/search?q=%E5%9B%BE%E7%89%87lisa&FORM=IQFRBA&id=29754A4BF0C1FB8DFE4D05E2C7F6600896C54071)
  3. 下载视频 (https://www.ixigua.com/c15afebf-9bc3-4eae-a044-dc4ad635561e)

如上都是要下载的链接,具体代码如下所示:

 
import urllib.request
urllib.request.urlretrieve(url = 'http://www.baidu.com', filename = 'baidu.html')
urllib.request.urlretrieve(url = 'https://cn.bing.com/images/search?q=%E5%9B%BE%E7%89%87lisa&FORM=IQFRBA&id=29754A4BF0C1FB8DFE4D05E2C7F6600896C54071', filename = 'lisa.jpeg')
urllib.request.urlretrieve(url = 'https://www.ixigua.com/c15afebf-9bc3-4eae-a044-dc4ad635561e', filename = 'ciji.mp4')

1.4 urllib.request请求对象定制

使用urllib.request请求对象定制,(urllib.request请求对象定制一般用于加参数),一般是遇到了UA反爬, urllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None)

  • url:请求的URL
  • data:请求的参数。必须传bytes(字节流)类型的,如果是字典,可以先用urllib.parse模块里的urlencode( )编码。
  • headers:请求头。它是一个字典类型的数据。
  • origin_req_host:请求方的host名称或者IP地址。
  • unverifiable:该请求是否是无法验证的,默认为False,意思是说用户没有足够权限来选择接收这个请求的结果。例如,请求一个HTML文档中的图片,但是没有自动抓取图像的权限,这时unverifiable的值就是True。
  • method:请求使用的方法,类型是一个字符串,比如GET、POST。
  1. url组成

    https://www.baidu.com/s?wd=周杰伦

    • 协议:https
    • 主机:www.baidu.com
    • 端口号:443(不同协议有不同的端口号,https协议的端口号就是443)
    • 路径:/s
    • 参数:?wd=周杰伦
    • 锚点
  2. UA介绍

    User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件等

  3. UA反爬

  • Request(url = url, headers = headers):这个方法,让对象有UA这个变量
import urllib.request

url = "https://www.baidu.com"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.46'
}
request = urllib.request.Request(url = url, headers = headers)
respons = urllib.request.urlopen(request)  # 因为urlopen方法中不能存储字典 所以headers不能传递进去,只能够通过Request()方法来进行
print(respons.read().decode('utf-8'))


  1. header反爬

    Cookie反爬百度翻译

    对于一些网站,会有一些反爬虫手段,会检测header头,headers头包括了很多,比如ua,cookie,refer,所以都加进headers比较保险,比如爬取https://fanyi.baidu.com/v2transapi?from=en&to=zh详细信息

    import urllib.request
    import urllib.parse
    import json
    
    url = "https://fanyi.baidu.com/v2transapi?from=en&to=zh"
    headers = {
        'Cookie': '__bid_n=18466562d5dc2d8c534207; '
                  'BDUSS=9DRjRrNTl1dXFCTzNNZTc1ZWpmZU9jUkdYNFcyVHl5a1hOcTNXZE5pUGF4YXRqSVFBQUFBJCQAAAAAAAAAAAEAAADbWkf0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANo4hGPaOIRjcm; BDUSS_BFESS=9DRjRrNTl1dXFCTzNNZTc1ZWpmZU9jUkdYNFcyVHl5a1hOcTNXZE5pUGF4YXRqSVFBQUFBJCQAAAAAAAAAAAEAAADbWkf0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANo4hGPaOIRjcm; FEID=v10-bbf79465cb6037e17e571a6bd4778a560c40c4d7; jsdk-uuid=28a8c7fd-c29e-40bd-888e-10f41c0476d2; __xaf_fpstarttimer__=1672832332898; __xaf_thstime__=1672832334824; __xaf_fp timer__=1672832334825; BIDUPSID=87ADCB36D4C9FF15F511265294A52531; PSTM=1673227758; ZFY=1tYHakIfh9P4Zs4ao2uBbbOb38KPwAl5c2lM9h5TeKk:C; BAIDUID=9A24FA0CAF55F1DACB732D74992B350F:FG=1; BAIDUID_BFESS=9A24FA0CAF55F1DACB732D74992B350F:FG=1; BA_HECTOR=858ka1802g0h01800l20ak1j1hurv9k1l; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; FP +fukuYQtl1eUTzHvBlfQsjjyYdiXuRzX1zsbAZwpdVuIXYLvSIkYtGkxHjoRp1buGX/lofZGr8lerJYMhKosXxEl/Dhqk6tkYxayk3fIlUw4cVT4xVM6m21Ck+0WDMSOjymIsJEbkFskj1eATjH8VFZRWR8078Iu+O1Z/tCG9hbpwBzE21L1wQo/I4J7FS6hBFlIWKQ2w967pPJe369zbp203uaQDVvC7UYGlY1xwWuyqFN92sN3LHdRXftTs3ZsVSdJqe/pODK0D7A7n5/eyoUIflB1sXEgwLZD0ufwnWdmD1BlWZ6gt5Bo7q1kPv91G0CVOOJSGLJXKxlBOzCNWwgi9TGd0lDjrUBoy1I9D5LAgr1+gkgKAcZudMBpw==|8ai2YuWWsyPXkm5w5m+95xsNId+S+fQtfoYFqt3YdbY=|10|db95d3de956a427e3cda41472f77f3d1; RT="z=1&dm=baidu.com&si=27283d9b-bcfd-43e4-b1e4-059c515e01d4&ss=le6yeron&sl=0&tt=0&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ul=499&hd=4ae"; delPer=0; PSINO=7; H_PS_PSSID=38186_36545_38092_38132_37906_38148_37989_38179_38171_36802_37920_37900_26350_37959_38101_38008_37881; APPGUIDE_10_0_2=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1676605158; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1676605262; ab_sr=1.0.1_OWQ5NzZhMWMwMDIxNTI1MzdmNGI1MjUxMDFmZDMwZWI0ZjRlNDM4MmUwMGNkNGMyOGFmNjE4MzMwOWUyNWJhNmU4ZWM1ZGExYjljN2MzYjM3YmZhYTQwYjc4YTUwYzUwNWFlMTk3ODkyMTNmNjdiODQyOTkwNjlmMzY2YmRjZDc3NDQyYzNjM2MxMGRlYjE0MDIyNGZmOWU4MjMxYzc5ZmQzYzc4N2EyZjYyZGMyMTI4YjQyYWYyZGQwYjYzNGI2',
    }
    data = {
            'from': 'en',
            'to': 'zh',
            'query': 'lo',
            'transtype': 'realtime',
            'simple_means_flag': '3',
            'sign': '646722.867699',
            
            'domain': 'common',
    }
    data = urllib.parse.urlencode(data).encode('utf-8')  # post传递的数据必须要进行编码
    
    request = urllib.request.Request(url=url, data=data, headers=headers)
    respons = urllib.request.urlopen(request)
    respons = respons.read().decode('utf-8')
    
    obj = json.loads(respons)
    print(obj)
    
    

EditPluse ctrl + h进行正则替换

在这里插入图片描述

在这里插入图片描述

Cookie反爬微博

import urllib.request

url = 'https://weibo.cn/?sudaref=m.weibo.cn'
headers = {
    'cookie': '_T_WM=7aa603ba59a9ed8dd9a649ebf7f72096; WEIBOCN_WM=3349; MLOGIN=0; loginScene=103012; '
              'SUB=_2A25O9FdPDeRhGeFG6VMT9CrJyz2IHXVqF3kHrDV6PUJbktANLWjWkW1NfhtDVUi3jOfI2JqqDIDRHoZHaVJccyKU; '
              'SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9W5v0TpzO8Ap5GqqGM50SpyJ5JpX5KzhUgL'
              '.FoMReo2EShBfeh22dJLoIp7LxKML1KBLBKnLxKqL1hnLBoMN1hzpeoBXSK5p; SSOLoginState=1676683039',
    'referer': 'https://login.sina.com.cn/' , # referer  判断当前路径是不是由上一个路径进来的    一般情况下 是做图片防盗链
    'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/110.0.0.0 Mobile Safari/537.36 '
}
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')  # 这个编码方式取决于我们要爬取的类容的编码方式

with open('weibo.html', 'w', encoding='utf-8') as fp:
    fp.write(content)


对于headers头需要添加的数据,一般有如下的规律:

  • 不需要headers头:一般是http协议的地址,爬取百度http://www.baidu.com
  • 对于https协议的地址,一般需要UA,爬取百度https://www.baidu.com
  • 对于需要查看的数据是在登录之后看到的,就需要Cookie,爬取微博https://weibo.cn/
  • 对于所需要的数据如果在数据中存在图片,一般需要’referer’

1.5urllib.request完成POST请求
import urllib.request

url = "http://www.baidu.com"

respons = urllib.request.urlopen(request) 
print(respons.read().decode('utf-8'))

如上代码所示,如果是请求`https://www.baidu.com就需要UA反爬,就需要在请求中添加headers头,使用了Request方法,以POST方式请求,需要以POST方式传递参数,也需要使用Request方法

  • Request(url,data,headers):data是post传递的参数,是字节,要进行utf-8编码
import urllib.request
import urllib.parse
import json

url = "https://fanyi.baidu.com/sug"
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.46'
}
data = {
    'kw': 'spider'
}
data = urllib.parse.urlencode(data).encode('utf-8')  # urlencode():把data变成kw=spider样的形式,如果data中有中文的话,中文会被进行url编码

request = urllib.request.Request(url=url, data=data, headers=headers)
respons = urllib.request.urlopen(request)
respons = respons.read().decode('utf-8')

obj = json.loads(respons)
print(obj)

1.6 编解码
  1. 编码集的演变

    由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。你可以想得到的是,全世界有上百种语言,日本把日文编到Shift\_JIS里,韩国把韩文编到Euc‐kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode
    
  2. 编解码

    import urllib.request
    import urllib.parse
    
    url = "https://www.baidu.com/s?wd="
    headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.46'
    }
    name = urllib.parse.quote('周杰伦')  # 把周杰伦编码成url编码的格式,url不能够识别中文,只能够把中文进行编码
    url = url + name
    request = urllib.request.Request(url=url, headers=headers)
    respons = urllib.request.urlopen(request)
    print(respons.read().decode('utf-8'))
    
    import urllib.parse
    import urllib.request
    
    base_url = 'https://www.baidu.com/s?'
    data = {
        'wd': '周杰伦',
        'sex': '男'
    }
    name = urllib.parse.urlencode(data)
    url = base_url + name
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.46'
    }
    request = urllib.request.Request(url=url, headers=headers)
    response = urllib.request.urlopen(request)
    contents = response.readline().decode('utf-8')
    print(contents)
    
  3. 为什么要进行编码

    当我们访问https://www.baidu.com/s?wd=周杰伦&sex=男这个链接的时候,发现浏览器会把中文字符进行url编码,这说明服务器不能够识别中文,要想识别中文必须把中文进行url编码,我们写的代码没有浏览器自动进行url编码,所以需要我们手动编码

在这里插入图片描述

2.urllib.error模块的使用

urllib.error.HTTPError:和urllib.error.HTTPError,其中urllib.error.URLError是urllib.error.URLError的子集

import urllib.request
import urllib.error
url = 'https:action=&start=0&limit=20'

headers = {
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/110.0.0.0 Mobile Safari/537.36 '
}
try:
    request = urllib.request.Request(url=url, headers=headers)
    response = urllib.request.urlopen(request)
    contents = response.read().decode('utf-8')
    print(contents)
except urllib.error.HTTPError:
    print(urllib.error.HTTPError)
except urllib.error.URLError:
    print('urllib.error.URLError')

3.urllib.parse模块的使用

2.1 urllib.parse模块quote()
import urllib.parse

base_url = 'https://www.baidu.com/s?wd='
name = urllib.parse.quote('周杰伦')
url = base_url + name
print(url)
2.1 urllib.parse模块urlencode()
import urllib.parse

base_url = 'https://www.baidu.com/s?'
data = {
    'wd': '周杰伦',
    'sex': '男'
}
name = urllib.parse.urlencode(data)
url = base_url + name
print(url)

3. 请求

1.get请求

1.1 下载豆瓣电影一页类容
import urllib.request

url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20'

headers = {
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/110.0.0.0 Mobile Safari/537.36 '
}
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
contents = response.read().decode('utf-8')
# open方法默认情况下使用的是gbk的编码  如果我们要想保存汉字 那么需要在open方法中指定编码格式为utf-8
with open("douban.json", 'w', encoding='utf-8') as fp:
    fp.write(contents)

找我们需要数据的包就行了

1.2 下载豆瓣电影前10页类容
# import urllib.request
#
# fp = open("douban1.json", 'a', encoding='utf-8')
# for i in range(0, 10):
#     url = f"https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start={i*20}&limit=20"
#     headers = {
#         'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) '
#                       'Chrome/110.0.0.0 Mobile Safari/537.36 '
#     }
#     request = urllib.request.Request(url=url, headers=headers)
#     response = urllib.request.urlopen(request)
#     contents = response.read().decode('utf-8')
#     # open方法默认情况下使用的是gbk的编码  如果我们要想保存汉字 那么需要在open方法中指定编码格式为utf-8
#     fp.write(contents)
# fp.close()
#
#
#

import urllib.request
import urllib.parse


# 下载豆瓣电影前10页的数据
# (1) 请求对象的定制
# (2) 获取响应的数据
# (3) 下载数据

def get_request(start_page):
    """
    请求对象的定制
    :param start_page:
    :return: request
    """
    base_url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&'
    data = {
        'start': (start_page - 1) * 20,
        'limit': 20
    }
    data = urllib.parse.urlencode(data)
    url = base_url + data
    headers = {
        'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/110.0.0.0 Mobile Safari/537.36 '
    }
    request = urllib.request.Request(url=url, headers=headers)
    return request


def get_contents(request):
    """
    获取响应的数据
    :param request:
    :return:
    """
    response = urllib.request.urlopen(request)
    contents = response.read().decode('utf-8')
    return contents


def down_load(contents, start_page):
    """
    下载数据
    :param contents:
    :return:
    """
    with open('douban_' + str(start_page) + '.json', 'w', encoding='utf-8') as fp:
        fp.write(contents)


if __name__ == '__main__':
    start_page = int(input('输入开始页:'))
    end_page = int(input('输入结束页:'))

    for item in range(start_page, end_page + 1):
        request = get_request(item)
 
        contents = get_contents(request)

        down_load(contents, item)


对数据包进行规律寻找

2.POST请求

http://www.kfc.com.cn/kfccda/storelist/index.aspx获取肯德基门店信息

import urllib.request
import urllib.parse


def create_request(item):
    url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/110.0.0.0 Mobile Safari/537.36 '
    }
    data = {
        'cname': '安庆',
        'pid': '',
        'pageIndex': item,
        'pageSize': '10',
    }
    data = urllib.parse.urlencode(data).encode('utf-8')
    request = urllib.request.Request(url=url, data=data, headers=headers)
    return request


def get_contents(request):
    response = urllib.request.urlopen(request)
    contents = response.read().decode('utf-8')
    return contents


def down_load(item, contens):
    with open('kdj_' + str(item) + '.json', 'w', encoding='utf-8') as fp:
        fp.write(contens)


if __name__ == '__main__':
    start_page = int(input('请输入开始页面:'))
    end_page = int(input('请输入结束页面:'))

    for item in range(start_page, end_page + 1):
        request = create_request(item)

        contents = get_contents(request)

        down_load(item, contents)


4. 设置代理

1.代理

IP快代理

# 找代理,快代理
# ctrl+B查看方法源码

import urllib.request

url = 'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 '
                  'Safari/537.36 Edg/110.0.1587.46 '
}
request = urllib.request.Request(url=url, headers=headers)

proxies={
    'http':'182.139.110.52:9000'
}

hander = urllib.request.ProxyHandler(proxies=proxies)
opener = urllib.request.build_opener(hander)
response = opener.open(request)

content = response.read().decode('utf-8')

with open('ip.html', 'w', encoding='utf-8') as fp:
    fp.write(content)


2. 代理池

import urllib.request

proxies_pool = [
    {'http':'118.24.219.151:16817'},
    {'http':'118.24.219.151:16817'},
]

import random

proxies = random.choice(proxies_pool)

url = 'http://www.baidu.com/s?wd=ip'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

request = urllib.request.Request(url = url,headers=headers)

handler = urllib.request.ProxyHandler(proxies=proxies)

opener = urllib.request.build_opener(handler)

response = opener.open(request)

content = response.read().decode('utf-8')

with open('daili.html','w',encoding='utf-8')as fp:
    fp.write(content)

爬取IP地址:(如下是爬取IP地址的代码)

import urllib.request
import urllib.error
from lxml import etree
import ssl
ssl._create_default_https_context = ssl._create_unverified_context


headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,'
              'application/signed-exchange;v=b3;q=0.7',
    'Connection': 'keep-alive',
    'Cookie': 'Hm_lvt_b72418f3b1d81bbcf8f99e6eb5d4e0c3=1677292598; __bid_n=186866df21b7efff304207; '
              'FP '
              '/zZueyxnokzsW3bVXmmLR1SIDMmPelKP0A211kb0iTlpxm8z6lhMyc3fIWVdwYLh/QN5278tdQu4E9k8z'
              '+q5ephjxtSWxglAngFFwPtwwK2IEkwm/MkdI6S6Q'
              '+ySag50bXJTkNTb6XGpMPg6DmJ3fINHh3BgoGxCVrn7s5c3p4IEdYKYqDtgAQl4eackpeuZbhz1pHi6yt1YnI+efmf+eSax6bl'
              '/ZTnBuH8g1bdun1WcGOWQFEs+uBYMPc5dxA9al8413VZiRcvF1a6lJr1/pPgVuUCrpyhAPmWdHLADi4V9UfUGs9C6HLWl'
              '+vVg2x5lxLhtKq4g0z4QyAfj0HHlKsvjWw==|YF4yavlOLDHxlUia7WtdqPp4ETkqPePhio/2jx5rMfE=|10'
              '|0f7f1b34809fe5066fcf5503c009f8d6; Hm_lpvt_b72418f3b1d81bbcf8f99e6eb5d4e0c3=1677292959',
    'Host': 'ip.jiangxianli.com',
    'Referer': 'https://ip.jiangxianli.com/?page=2',
    'sec-ch-ua': '"Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"',
    'sec-ch-ua-mobile': '?1',
    'sec-ch-ua-platform': '"Android"',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'same-origin',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/110.0.0.0 Mobile Safari/537.36',
}
ip = []
try:
    for i in range(1, 11):
        url = f"https://ip.jiangxianli.com/?page={i}"
        requst = urllib.request.Request(url=url, headers=headers)
        response = urllib.request.urlopen(requst)
        content = response.read().decode('utf-8')

        tree = etree.HTML(content)
        ip_list = tree.xpath("//tbody//tr//td[1]/text()")
        port_list = tree.xpath("//tbody//tr//td[2]/text()")
        for item in range(len(ip_list)):
            str = ip_list[item] +':'+ port_list[item]
            ip.append(str)
    print(ip)
except urllib.error.URLError as error:
    print(error)

爬虫代码思路

  1. 第一步看预览,看其中是否有我们需要的信息

    一般来说,像比较复杂的名称包含的信息一般较多,所以一般是找这种包名称比较长的查看

  2. 第二步观察请求方式和URL

    不同的请求方式对应的代码也不相同,如果是get请求不需要data数据,如果是post请求,需要查看表单数据

在这里插入图片描述

如下是封装好的类:

import urllib.request
import urllib.parse
from lxml import etree
import json
import jsonpath

class Content:
    def __init__(self, url):
        self.url = url

    def create_request(self, data=0):
        """
        得到请求
        :param data: post请求数据
        :return: 返回请求
        """
        headers = {
            'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, '
                          'like Gecko) '
                          'Chrome/110.0.0.0 Mobile Safari/537.36 '
        }
        if data != 0:
            data = urllib.parse.urlencode(data).encode('utf-8')
            request = urllib.request.Request(url=self.url, data=data, headers=headers)
        else:
            request = urllib.request.Request(url=self.url, headers=headers)
        return request

    def get_contents(self, request, ip=0):
        """
        得到数据
        :param request: create_request()得到的数据
        :param ip: 有ip就开启代理
        :return: 返回数据
        """
        proxies = {
            'http': ip
        }
        if ip:
            hander = urllib.request.ProxyHandler(proxies=proxies)
            opener = urllib.request.build_opener(hander)
            response = opener.open(request)  # 得到response返回的数据流
        else:
            response = urllib.request.urlopen(request)
        contents = response.read().decode('utf-8')
        return contents

    def down_load(self, name, contens):
        """
        数据下载
        :param name: 类容存储文件名称
        :param contens: 类容
        :return:
        """
        with open(name, 'w', encoding='utf-8') as fp:
            fp.write(contens)

    def get_content(self, name):
        """
        get型请求下载数据到文件
        :param name: 类容存储文件名称
        :return:
        """
        request = self.create_request()
        contents = self.get_contents(request)
        self.down_load(name, contents)

    def post_content(self, name, data):
        """
        post型请求下载数据到文件
        :param name: 类容存储文件名称
        :param data: post方法传递数据
        :return:
        """
        request = self.create_request(data)
        contents = self.get_contents(request)
        self.down_load(name, contents)

    def getdl_content(self, ip):
        """
        get型请求并使用代理
        :param ip: 开启代理ip
        :return:
        """
        request = self.create_request()
        contents = self.get_contents(request, ip)
        self.down_load(name, contents)

    def postdl_content(self, name, ip, data):
        """
        post型请求代理ip下载数据到文件
        :param name:
        :param ip:
        :param data:
        :return:
        """
        request = self.create_request(data)
        contents = self.get_contents(request, ip)
        self.down_load(name, contents)

    def get(self, name, Xpath=0, Json=0):
        if Xpath:
            parser = etree.HTMLParser(encoding='utf-8')
            tree = etree.parse(name, parser=parser)
            li_list = tree.xpath(Xpath)
            return li_list
        else:
            obj = json.load(open(name, 'r', encoding='utf-8'))
            li_list = jsonpath.jsonpath(obj, Json)
        return li_list



baidu = Content('http://www.baidu.com')
baidu.get_content('1.html')
print(baidu.get(name='1.html', Xpath='//*[@id="index-bn"]/text()'))

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安全天天学

你的鼓励是对我最大的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值