资讯详情

学习网络爬虫(1)

1 学习网络爬虫

所有可以在网上看到的数据都可以通过爬虫程序保存。

Robots网络爬虫排除标准设计网络爬虫排除标准Robots协议告诉搜索引擎哪些页面可以爬取,哪些页面不可以爬取。

2 网络爬虫的基本问题

  • Python爬虫的过程是什么? 1.获取网页 2.分析网页(提取数据)3.存储数据

  • 三个过程的技术实现是什么? 1.获取网页 获取网页的基本技术:request、urllib和selenium(模拟浏览器) 获取网页的先进技术:多线程多线程抓取、登录抓取、突破IP封禁和服务器抓取。 2.解析网页 分析网页的基本技术:re正则表达式,BeautifulSoup和lxml。 分析网页的先进技术:解决中文乱码 3.存储数据 存储数据的基本技术:txt文件和存入csv文件 存储数据的先进技术:存储数据MySQL数据库和存入MongoDB数据库。

3 编写第一个网络爬虫

写第一个爬虫

首先,自行安装Anaconda。我们会用它自带的Jupiter编写网络爬虫。 爬网站为www.santostang.com”,为《Python作者从入门到实践的博客,感谢作者给我们带来了这么好的作品。 首先,让我们来看看一个简单的爬虫程序。 第一步,获取页面

import requests link = "http://www.santostang.com/" headers = { 
        'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Fierfox/3.5.6'} r = requests.get(link, headers= headers) print(r.text) 

用request的headers伪装成浏览器访问。 第二步是提取数据

import requests from bs4 import BeautifulSoup link = "http://www.santostang.com/" headers = { 
        'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Fierfox/3.5.6'} r = requests.get(link, headers= headers) soup = BeautifulSoup(r.text, "lxml") title = soup.find("h1", class_="post-title").a.text.strip() print (title) 

提取的数据如下:

第四章 – 4.3 通过selenium 抓取模拟浏览器

第三步:存储数据

import requests from bs4 import BeautifulSoup link = "http://www.santostang.com/" headers = { 
        'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Fierfox/3.5.6'} r = requests.get(link, headers= headers)
soup = BeautifulSoup(r.text, "lxml")
title = soup.find("h1", class_="post-title").a.text.strip()
print (title)

with open('title1.txt',"a+") as f:
    f.write(title)
    f.close()

Python 基础试题

试题1:请使用Python中的循环打印输出从1到100的所有的奇数。

for i in range(1, 101):
    if i % 2:
        print(str(i) + " ",end='')

试题2 :请将字符串’你好$$$我正在学Python@####现在需要&%&%&%修改字符串’中的符号换为空格。

str1 = '你好$$$我正在学Python@####现在需要&%&%&%修改字符串'
str2 = str1.replace('$$$', ' ').replace('@####', ' ').replace('&%&%&%', ' ')
print(str2)

试题3:输出 9 × 9 9 \times 9 9×9乘法口诀表。

for i in range(1, 10):
    for j in range(1, i + 1):
        print(str(i) + '*' + str(j) + ' ', end = '')
    print()

试题4:请写出一个函数,当输入函数变量月利润为I时,能返回应发放奖金的总数。例如,输出“利润为100000元时,应发放奖金总数为10000元”其中,企业发放的奖金根据利润提成。利润D 低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%;利润在20万元到40万元之间时,高于20万元的部分可提成5%;利润在40万元到60万元之间时,高于40万元的部分可提成3%;利润在 60 万元到 100 万元之时,高于60万元的部分可提成1.5%;利润高于100万元时,超过100万元的部分按1%提成。

def calcute_profit(I):
    I = I / 10000
    if I <= 10:
        a = I * 0.01
        return a * 10000
    elif I <= 20 and I > 10:
        b = 0.25 + I * 0.075
        return b * 10000
    elif I <= 40 and I > 20:
        c = 0.75 + I * 0.05
        return c * 10000
    elif I <= 60 and I > 40:
        d = 0.95 + I * 0.03
        return d * 10000
    elif I <= 60 and I > 100:
        e = 2 + I * 0.015
        return e * 10000
    else:
        f = 2.95 + I * 0.01
        return f * 1000
I = int(input('净利润:'))
profit = calcute_profit(I)
print ('利润为%d元时,应发奖金总数为%d元' % (I, profit))

试题5:用字典的值对字典进行排序,将{1:2,3:4,4:3,2:1,0:0}按照字典的值从小到大排列。

import operator
x = { 
        1:2,3:4,4:3,2:1,0:0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))
print(sorted_x)

试题6:请问以下两段代码的输出分别是什么?

a = 1
def fun(a):
	a = 2
fun(a)
print (a)

答案:输出1

a = []
def fun(a):
	a.ppend(1)
fun(a)
print (a)

答案:输出 1 试题7:请问一下两段代码的输出分别是什么?

class Person:
	name = "aaa"

p1 = Person()
p2 = Person()
p1.name = "bbb"
print (p1.name)
print (p2.name)
print (Person.name)

bbb aaa aaa

class Person:
	name = []

p1 = Person()
p2 = Person()
p1.name.append(1)
print (p1.name)
print (p2.name)
print (Person.name)

[1] [1] [1]

4 静态网页抓取

需要安装request库,还请读者自行安装。

4.1 获取相应内容

在request中,最常用的功能是获取某个网页的内容。现在我们使用 request获取个人博客主页的内容。

import requests
r = requests.get('http://www.santostang.com/')
print ("文本编码:", r.encoding)
print ("响应状态码:", r.status_code)
print ("字符串方式的响应体:", r.text)

上例的说明如下: (1)r.text是服务器响应的内容,会自动根据响应头部的字符编码进行解码。 (2)r.encoding是服务器内容使用的文本编码。 (3)r.status_code用于检测响应的状态码;返回5xx则表示服务期错误响应。我们可以用r.status_code来检测请求是否正确响应。 (4)r. content 是字节方式的响应体,会自动解码gzip和deflate编码的响应数据。 (5)r.json()是request中内置的JSON解码器。

4.2 定制requests

有些网页需要定制requests的参数才能获取需要的数据,包括传递URL参数、定制请求头、发送POST请求、设置超时等。

4.2.1 传递URL参数

往往以字典的形式传递参数。

import requests
key_dict = { 
        'key1':'value1','key2':'value2'}
r = requests.get('http://httpbin.org/get', params=key_dict)
print ("URL已经正确的编码:", r.url)
print ("字符串方式的响应体:\n", r.text)

URL已经正确的编码: http://httpbin.org/get?key1=value1&key2=value2 字符串方式的响应体: { “args”: { “key1”: “value1”, “key2”: “value2” }, “headers”: { “Accept”: “/”, “Accept-Encoding”: “gzip, deflate”, “Host”: “httpbin.org”, “User-Agent”: “python-requests/2.25.1”, “X-Amzn-Trace-Id”: “Root=1-6270f40e-0afeada86d2efeab067bc977” }, “origin”: “112.38.217.11”, “url”: “http://httpbin.org/get?key1=value1&key2=value2” }

4.2.2 定制请求头

查看请求头的信息:

GET / HTTP/1.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 Cache-Control: max-age=0 Connection: keep-alive Cookie: PHPSESSID=ajfv5ma4f58pe1on1hbff1na01 Host: www.santostang.com Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36 Edg/101.0.1210.32

提取请求头中重要的部分,可以把代码写成;

import requests
headers = { 
        
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36 Edg/101.0.1210.32',
    'Host':'www.santostang.com'
}
r = requests.get('http://www.santostang.com/',headers= headers)
print ("响应状态码:",r.status_code)

4.2.3 发送POST请求

除了GET请求外,有时还需要发送一些编码为表单形式的数据,比如说登录的时候请求就为POST,因为如果用GET请求,密码就会显示在URL中,安全性极低。如果要实现POST请求,只需要简单地传递一个字典给request中的data参数,这个数据字典就会在发出请求的时候自动编码为表单形式。

import requests
key_dict = { 
        'key1':'value1','key':'value2'}
r = requests.post('http://httpbin.org/post',data=key_dict)
print (r.text)

{ “args”: {}, “data”: “”, “files”: {}, “form”: { “key”: “value2”, “key1”: “value1” }, “headers”: { “Accept”: “/”, “Accept-Encoding”: “gzip, deflate”, “Content-Length”: “22”, “Content-Type”: “application/x-www-form-urlencoded”, “Host”: “httpbin.org”, “User-Agent”: “python-requests/2.25.1”, “X-Amzn-Trace-Id”: “Root=1-627107a1-6044b25d30954b6b30272954” }, “json”: null, “origin”: “112.38.217.11”, “url”: “http://httpbin.org/post” }

可以看到,form 变量的值为 key_dict 输入的值,这样一个 POST 请求就发送成功了。

4.2.4 超时

意思就是,如果服务器在 timeout 秒内没有应答,就返回异常。 将timeout设置为0.001试一下

import requests
link = "http://www.santostang.com/"
r = requests.get(link, timeout= 0.001)

返回的异常为:

ConnectTimeout: HTTPConnectionPool(host=‘www.santostang.com’, port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001E27188FBB0>, ‘Connection to www.santostang.com timed out. (connect timeout=0.001)’))

异常值的意思为,时间限制在0.001秒内,连接到地址为 www.santostang.com 的时间已到。

5 动态网页抓取

如果使用AJAX加载的动态网页,爬取里面动态加载的内容的方法有二: (1)通过浏览器审查元素解析地址。 (2)通过Selenium模拟浏览器抓取。

5.1 通过浏览器审查元素解析地址

import requests
link = """https://api-zero.livere.com/v1/comments/list?callback=jQuery1124029565129817049396_1651637402392&limit=10&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1651637402394"""
headers = { 
        
    'Host':'api-zero.livere.com',
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36'
}
r = requests.get(link,headers= headers)
print (r.text)

结果: >

综上所述,如果要爬取类似淘宝网评论这种用AJAX加载的网页的话,从网页源代码中是找不到想要的数据的。需要用浏览器的审查元素,找到真实的数据地址。然后爬取真实的网站。 爬取评论内容;

import json
json_string = r.text
json_string = json_string[json_string.find('{'):-2]
json_data = json.loads(json_string)
comment_list = json_data['results']['parents']
for eachone in comment_list:
    message = eachone['content']
    print (message)

运行结果为:

爬取多页: (现在爬不了了,URL的变换规律换了)

import requests
import json
def single_page_comment(link):
    headers = { 
        
        'Host':'api-zero.livere.com',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36'
    }
    # 获取 json 的string
    json_string =  r.text
    json_string = json_string[json_string.find('{'):-2]
    json_data = json.loads(json_string)
    comment_list = json_data['results']['parents']
    for eachone in comment_list:
        message = eachone['content']
        print (message)
        
for page in range(0,4):
    link1 = "https://api-zero.livere.com/v1/comments/list?callback=jQuery112403473268296510956_1531502963311&limit=10&offset="
    link2 = "&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&_=1531502963316"
    page_str = str(page)
    link = link1 + page_str + link2
    print (link)
    single_page_comment(link)

5.2通过selenium模拟浏览器抓取

在上述的例子中,使用Chrome“检查”功能找到源地址还十分容易。但是有一些网站非常复杂,例如前面的天猫产品评论,使用“检查”功能很难找到调用的网页地址。除此之外,有一些数据真实地址的URL也十分冗长和复杂,有些网站为了规避这些抓取会对地址进行加密,造成其中的一些变量让人摸不着头脑。 首先,安装 selenium。 我们使用selenium打开一个浏览器和一个网页:

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("http://www.baidu.top")

标签: fv1连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台