python爬虫系列2--urllib.request

urllib属于python3.x自带的库,功能比较简单,可以拿来入门和练手。

官方手册:https://docs.python.org/3/library/urllib.html


+ 简单操作

import urllib.request

data = urllib.request.urlopen('https://www.douban.com')

print(data.version,data.status,data.reason,data.closed)

print(data.read().decode('utf-8'))


通过HTTP Analyzer抓包显示urlopen发送的网页请求内容为:

GET / HTTP/1.1

Accept-Encoding: identity

Host: www.douban.com

User-Agent: Python-urllib/3.6

Connection: close


+ 模拟浏览器访问

模拟浏览器需要使用urllib.request.Request对象


import urllib.request

url = "https://www.douban.com"

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.64',

'Host':'www.douban.com',

'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',

'Connection':'keep-alive'}

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

data = urllib.request.urlopen(request)

print(data.status)


+ post数据到服务器

如果要以POST发送一个请求,只需要把参数data以bytes形式传入。


import urllib.request

import urllib.parse


url = "http://httpbin.org/post"

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.64',

'Host':'httpbin.org',}

dict = {'name':'chenkaifang'}

data = urllib.parse.urlencode(dict).encode('utf-8')

request = urllib.request.Request(url=url,headers=headers,method='POST')

response = urllib.request.urlopen(request)

print(response.read().decode('utf-8'))


+ 简单模拟登陆

提交用户登录信息(用户名和密码),不同网站可能需要的东西不一样。parse的 urlencode 方法是将一个字典或者有顺序的二元素元组转换成为URL的查询字符串。

使用Cookie和使用代理IP一样,也需要创建一个自己的opener。在HTTP包中,提供了cookiejar模块,用于提供对Cookie的支持。http.cookiejar功能强大,我们可以利用本模块的CookieJar类的对象来捕获cookie并在后续连接请求时重新发送,比如可以实现模拟登录功能。该模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。

它们的关系: CookieJar–派生–>FileCookieJar–派生–>MozillaCookieJar和LWPCookieJar

工作原理:创建一个带有cookie的opener,在访问登录的URL时,将登录后的cookie保存下来,然后利用这个cookie来访问其他网址。查看登录之后才能看到的信息。


(1)首次无cookie手动输入验证码登陆豆瓣

首次无cookie登陆有时需要用户输入验证码,可以将验证码图片下载到本地后手动输入,请求头和POST数据可以在浏览器中登陆检查元素(勾选Preserve log)找到浏览器发出的Login请求包,根据其格式填写自己的请求头。


import urllib.parse

import urllib.request

import re

import time


headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 OPR/53.0.2907.68',

'Host':'accounts.douban.com',

'Connection':'keep-alive',

'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',

'Referer':'https://accounts.douban.com/login',

'Accept-Encoding':'zip, deflate, br',

'Accept-Language':'zh-CN,zh;q=0.9'

}

values = {'source':'None',

'redir':'https://www.douban.com',

'form_email':'xxx',

'form_password':'yyy',

'login':'登陆',

}


url = "https://accounts.douban.com/login"

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


def get_captcha_info():

captcha_info = dict()

response = urllib.request.urlopen(request)

if response.status == 200:

html = response.read().decode('UTF-8')

link_list = re.findall(r'src="https://www.douban.com.*?captcha.*?"', str(html))

link = link_list[0][5:-1]

urllib.request.urlretrieve(link,'xx.jpg')

print(link)

captcha_solution = input('请输入验证码:')

captcha_info['captcha-solution'] = captcha_solution


captcha_id_list = re.findall(r'id=.*?&',link)

captcha_id = captcha_id_list[0][3:-1]

captcha_info['captcha-id'] = captcha_id


return captcha_info

captcha_info = get_captcha_info()


if captcha_info:

values.update(captcha_info)


time.sleep(3)

data = urllib.parse.urlencode(values).encode('UTF-8')

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

response = urllib.request.urlopen(request)


print(response.status,response.version,response.reason,response.geturl())

print(response.read().decode('UTF-8'))


(2)首次携带cookie手动输入验证码登陆豆瓣


import urllib.parse

import urllib.request

import re

import time

import http.cookiejar


headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 OPR/53.0.2907.68',

'Host':'accounts.douban.com',

'Connection':'keep-alive',

'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',

'Referer':'https://accounts.douban.com/login',

'Accept-Encoding':'zip, deflate, br',

'Accept-Language':'zh-CN,zh;q=0.9'

}

values = {'source':'None',

'redir':'https://www.douban.com',

'form_email':'xxx',

'form_password':'yyy',

'login':'登陆',

}


url = "https://accounts.douban.com/login"

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


cookie = http.cookiejar.CookieJar()

cookie_support = urllib.request.HTTPCookieProcessor(cookie)

opener = urllib.request.build_opener(cookie_support)



def get_captcha_info():

captcha_info = dict()

response = opener.open(request)

if response.status == 200:

html = response.read().decode('UTF-8')

link_list = re.findall(r'src="https://www.douban.com.*?captcha.*?"', str(html))

link = link_list[0][5:-1]

urllib.request.urlretrieve(link,'xx.jpg')

print(link)

captcha_solution = input('请输入验证码:')

captcha_info['captcha-solution'] = captcha_solution


captcha_id_list = re.findall(r'id=.*?&',link)

captcha_id = captcha_id_list[0][3:-1]

captcha_info['captcha-id'] = captcha_id


return captcha_info

captcha_info = get_captcha_info()


if captcha_info:

values.update(captcha_info)


time.sleep(3)

data = urllib.parse.urlencode(values).encode('UTF-8')




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

response = opener.open(request)


print(response.status,response.version,response.reason,response.geturl())

print(response.read().decode('UTF-8'))



+ 爬取网页上的图片实例 urllib.request + re

import urllib.request

import socket

import re

import sys

import os

targetDir = r"D:\project\webdownload"

def destFile(path):

if not os.path.isdir(targetDir):

os.mkdir(targetDir)

pos = path.rindex('/')

t = os.path.join(targetDir,path[pos+1:])

return t

#url="https://www.douban.com/"

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

webheader={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}

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

webPage = urllib.request.urlopen(req)

#data = webPage.read().decode('UTF-8')

data = webPage.read().decode('gbk')

'''print(data)'''

'''对于re.findall,如果有多个匹配group,则会返回类似(xxx,yyy)的tuple,所以下面用link,t'''

for link,t in set(re.findall(r'(http:[^\s]*?(jpg|png|gif))', str(data))):

print(link)

try:

urllib.request.urlretrieve(link, destFile(link))

except():

print('失败')

(1)利用urllib.request.urlretrieve(url, filename = 本地文件地址)。

(2)一般来说,URL标准中只会允许一部分ASCII字符比如数字、字母、部分符号等,而其他的一些字符,比如汉字等,是不符合URL标准的。此时,我们需要编码。如果要进行编码,我们可以使用urllib.request.quote()进行。

(3)用F12显示网页采用的charset=gb2312的编码,但是用decode("gb2312")时报错:UnicodeDecodeError: 'gb2312' codec can't decode byte 0x90 in position 34461: illegal multibyte sequence。

解决方案:使用第三方库chardet检测网页的真正编码方式,如果安装了Anaconda,chardet就已经可用了。chardet.detect(xxx)可以用来检测编码方式。

(4)gb2312编码的网页不需要解码直接使用正则即可。

(5)遇到/uploads/.../.jpg路径,实际图片下载路径为当前网址加上此路径。

(6)网页分为动态、静态和伪静态,htm或html静态或伪静态,asp、jsp、php、shtml等动态文件。javascript:alert(document.lastModified),将这句代码粘贴到所要测试页面的地址栏,回车即可出现时间提示。经过测试,静态页面提示的时间与系统时间不一样,而伪静态或动态页面则提示的时间与系统时间相同。urlopen的response中getheaders的Last-Modified返回最新修改时间。

(7)urllib.request适用于静态网页。

你可能感兴趣的:(Python)