Python3网络爬虫开发实战——第3章 基本库的使用

作者讲了两个库,一个是urllib,一个是requests。因为后者更为方便,强大,直接看requests就好

3.2 使用 requests

请求网页: r = requests.get(url,params=data)
是否得到响应:r.status_code
返回的结果如果是str类型,可以用json()解析并返回字典格式,但如果不是str类型,会抛出异常
r.content: 返回抓取对象的二进制码,这样知道链接就可以获取图片,音乐和视频,因为它们本质上就是二进制数据…(暗爽~)

import requests
r = requests.get('https://www.baidu.com/img/bd_logo1.png')
with open('bdlogo.png','wb') as f:
	f.write(r.content)

有些网站不给爬,我们就得修改headers
先给headers一个值,字典类型,如:

headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36(KHTML,like Gecko) '
                          'Chrome/65.0.3325.162 Safari/537.36'}
r.requests.get(url,headers=headers)

r.requests.post():跟get差不多,不过get就是在网址后面加数据,post能发送数据和文件,用的是字典类型

files = {'file':open('bdlogo.png','rb')}	# 以二进制的形式打开文件
r = requests.post("http://httpbin.org/post",files=files)

r.cookies:获取cookies,作用是保持网站的登录状态。先登录一次网站,然后然cookies内容复制下来,粘贴到headers里

headers = {'Cookies': '粘贴Cookies',
			'Host':'www.zhihu.com',
			'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36(KHTML,like Gecko) '
                          'Chrome/65.0.3325.162 Safari/537.36'}
r.requests.get(url,headers=headers)

这样就登录成功了


在用get()和post()时,是相当于用了两个浏览器打开网页。这样就会出现一个登录了网站,另一个没有登录的情况。这时我们就要用Session()

import requests
s = requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456789')
r = s.get('http://httpbin.org/cookies')
print(r.text)

有些网站需要检查SSL证书,我们可以用verify=False参数来跳过,但会出现红字警告,我们可以采用忽略警告的方式

import requests
from requests.packages import urllib3
urllib3.disable_warnings()
r = requests.get(url,verify=False)
print(r.status_code)

网站对于频繁的请求,会弹出验证码,或封IP,这时需要用上代理。用socks5代理,需要先安装
requests[socks] 这个库

import requests

proxies = {
    "http": "http://10.10.1.10:3128",	# 代理纯属虚构
    "https": "http://user:[email protected]:1080/",	# 有些代理需要用户名和密码
    "https": "socks5://user:password@host:port"
}
r = requests.get('https://www.taobao.com',proxies=proxies)
print(r.status_code)

有些网站特别是国外的,我们就设置超时,超过设置时间就报错, 还有些需要身份验证,输入用户名和密码的,用auth

r.requests.get(url, auth=('username','password'), timeout=10)

还可以想要发送的请求先打个包。然后一起发送出去。

from requests import Request,Session

url = 'http://httpbin.org/post'
data = {
    'name': 'germey'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36(KHTML,like Gecko) '
                  'Chrome/65.0.3325.162 Safari/537.36'
}
s = Session()
req = Request('POST', url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)
3.3 正则表达式

常用的匹配规则,有需要就翻一下,能记就记
通用匹配: 点星 .* ,能匹配所有任意字符,,但会涉及到贪婪匹配。避免贪婪就在*后面加个“?”。我们尽量做非贪婪匹配。
html节点经常会有换行,match(’’,content,re.S),用上re.S,就可以匹配节点与节点间的换行,
较常用的还有re.I,忽略大小写匹配
为了匹配方便,我们尽量使用search(),少用match
findall()获取 匹配的所有内容
sub()把不需要的字符去掉

3.4 抓取猫眼电影排行

抓取TOP100的电影名称、时间、评分、图片等
目标网址:https://maoyan.com/board/4

目标有分页,每页10部电影,点第二页观察网址的变化
第二页:https://maoyan.com/board/4?offset=10
第三页:https://maoyan.com/board/4?offset=20

可见,offset是偏移量,每页显示10个,显示 n+1 到 n+10 名次的电影。。要获取TOP100,就分开请求10次。然后用正则表达式提取相关信息

import requests
import re
import json
from requests.exceptions import RequestException
import time


def parse_one_page(html):	# 正则提取
    pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
                         + '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
                         + '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
    items = re.findall(pattern, html)
    for item in items:	# 处理结果,遍历提取并生成字典
        yield {
            'index':item[0],
            'image':item[1],
            'title':item[2].strip(),
            'actor':item[3].strip()[3:] if len(item[3]) > 3 else '',
            'time':item[4].strip()[5:] if len(item[4]) > 5 else '',
            'score':item[5].strip() + item[6].strip()
        }


def get_one_page(url):
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36(KHTML,like Gecko) '
                          'Chrome/65.0.3325.162 Safari/537.36'
        }
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        return None

def write_to_file(content):	 # 写入文件
    with open('result.txt','a',encoding='utf-8') as f:
        print(type(json.dumps(content))) 	# 实现字典的序列化
        f.write(json.dumps(content,ensure_ascii=False)+'\n') # ensure_ascii=False ,显示中文,不然显示unicode编码

def main(offset):
    url = 'https://maoyan.com/board/4?offset='+str(offset)
    html = get_one_page(url)
    for item in parse_one_page(html):
        print(item)
        write_to_file(item)

if __name__ == '__main__':
    for i in range(10):
        main(offset=i *10)  # 调用一次就下一页
        time.sleep(1)

猜你喜欢

转载自blog.csdn.net/byakki/article/details/87075332
今日推荐