Web搜索技术python爬虫学习记录

python数据爬取学习全记录

pycharm的安装

一开始我是用的anaconda里的spider来编写,但是电脑本身又装了python3.9,anaconda中是3.7,在配置环境的时候总容易搞糊涂,所以还是采用了pycharm来编写。
安装配置参考链接:https://www.runoob.com/w3cnote/pycharm-windows-install.html

request模块学习

1、 获取网页代码

import requests
url = "http://www.baidu.com"
html = requests.get(url)
print(html)

运行得:
报错信息
出现报错:返回值200 <respond [200]>
解决:
添加解决头参数User-Agent

2、 User-Agent
参考:https://blog.csdn.net/qq_44503987/article/details/104929111
(1) F12查看想要获取的网页代码,本机自带Microsoft edge如下
F12查看开发者界面黄框内表示浏览器发送的各种请求,任意点开一个,可以看到左边的扩展栏,点击蓝框标头,可以在下方找到User-Agent
找到头参数后,修改代码如下:

import requests
url = "http://www.baidu.com"
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'}
html = requests.get(url, headers=headers)
print(html)

但是此时还会出现报错:返回值200 <respond [200]>
这时还需修改print为html.text,即:

import requests
url = "http://www.baidu.com"
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'}
html = requests.get(url, headers=headers)
print(html)
print('***')
print(html.text)

运行得到结果:
爬取网页代码

beautifulsoup学习

通过以下文档学习基本用法,感受该函数的功能:
https://cuiqingcai.com/1319.html
https://blog.csdn.net/kikaylee/article/details/56841789
https://www.jianshu.com/p/8bb16b577a9f
通过以上的学习,可以学习到如何抓取网页代码中标签中的内容

反爬虫与反反爬虫

1、 反爬虫
反爬虫的常见手段大概有以下这些:
(1) 不返回网页,如不返回内容和延迟网页的返回时间
不返回网页是一种比较传统的反爬虫手段,也就是网站对爬虫请求返回
404 或者长时间不返回数据。
由于正常人在一般情况下不会短时间内访问大量网站,所以网站会根据IP 的访问量进行一定的封杀。
session 中会存储特定用户的属性和配置信息,当用户在 web 页面之间来回跳转时,session 的变量不会丢失,而如果一个 session 的访问量过大,也可能会遭到封杀。
当然,正如在第二部分提到的,User-Agent 识别也是一种最基础的封杀手段。
(2) 返回数据非目标网页,如返回错误页,返回空白页和爬取多页时间均返回同一页
很多时候,我们虽然能够爬取目标网站,但是爬虫返回的很可能是一个假的数据,比如返回空白页,或者返回的数据与网站显示的不一样等
(3) 增加获取数据的难度,如登录才可查看和登录时设置时间
最直接的就是将页面中的内容设置为登录后才可查看,然后可以在登录界面加入图形验证码等手段增加反爬难度

2、 反反爬虫
(1)修改请求头User-Agent
(2)增加爬虫时间间隔
利用Time库完成

import time
for i:
    spider(i) 
    # 这 里 是 一 段 伪 代 码, spider(i)是 具 体 的 爬 虫 代 码
time.sleep(10)

(3)使用代理
为了避免单个 IP 多次爬取导致被封,还可以使用 IIP 代理,示例如下:

import requests

link = "http://www.baidu.com"
proxies = {'http': 'http://xxx.xxx.xxx.xxx'} # 可 以 通 过 搜 索 引 擎 搜 索 的 方 式 自 行 获 取IP代 理 池
response = requests.get(link, proxies=proxies)

在做老师给的案例以及作业时,页相应出现过很多次3xx以及4xx,在仔细看了老师给的以上资料后,加入了User_Agent以及headers后有效解决了问题,虽然在作业中,一旦爬取一次后,就有很大可能接下来出现页响应412的错误,但是只要等待几分钟后又可继续爬取。

学习案例——爬取豆瓣电影榜单top250

可以参考一下链接以加强理解:
https://www.pianshen.com/article/7397136077/
https://blog.csdn.net/qq_39226755/article/details/83684361
https://www.jianshu.com/p/8a460be5a26e
https://blog.csdn.net/xing851483876/article/details/80578998

1、 直接通过print展示电影名称

import requests 
from bs4 import BeautifulSoupdef 
get_movies():
    headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'}
    movie_list = []
    for i in range(0, 10):       #range()创建一个整数列表 0 1 2 .....9
        link = 'https://movie.douban.com/top250?start=' + str(i * 25)   #一页只能展示出25个电影,所以每25个重新显示一次
        #print(link)
        r = requests.get(link, headers=headers, timeout=10)     #得到网页代码
        #print(r.text)
        print(str(i + 1), "页 响 应 状 态 码:", r.status_code)     #页响应状态码200表示OK客户端请求成功
        soup = BeautifulSoup(r.text, "lxml")                     #将html解析为对象进行处理,全部页面转变为字典或者数组
        #print(soup)
        div_list = soup.find_all('div', class_='hd')             #查找所有class属性为hd的div标签
        #print(div_list)
        for each in div_list:
            movie = each.a.span.text.strip()                     #获取class属性为hd的div标签的a标签的第一个span标签的文本
            movie_list.append(movie)
    return movie_list
get_movies()print(get_movies())

运行结果:
print展示豆瓣top250电影名可以看到每一页抓取的页响应状态都是200,表示抓取正常。
最后输出movies_list[]

2、 输出结果到txt文件,并加入电影具体信息

import requests
from bs4 import BeautifulSoup import json

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0'}

# 筛选信息
def get_top(url):
    respose = requests.get(url, headers=headers)
    soup = BeautifulSoup(respose.text, 'lxml')
    nums = soup.select('em')
    titles = soup.find_all('div', class_='hd')
    actors = soup.find_all('p', class_='')
    links = soup.select('ol li div a')
    rating_nums = soup.find_all('span', class_='rating_num')
    evaluate_numbers = soup.find_all('div', class_='star')
    evaluates = soup.find_all('span', class_='inq')
    # 将信息放进字典中
    for num, title, link, actor, rating_num, evaluate_number, evaluate in zip(nums, titles, links, actors, rating_nums,
                                                                              evaluate_numbers, evaluates):
        data = {  # 获取节点文本
            '排行': num.get_text(),
            '电影名字': title.get_text().split('\n')[2],
            '链接': link.get('href'),
            '导演人员': actor.get_text().strip(),
            '评分': rating_num.get_text().strip(),
            '评价人数': evaluate_number.get_text().split('\n')[4],
            '评价内容': evaluate.get_text()
        }
        print(data)
        # 写入文件
        file = open(r'D:\web_homework_1\douban.txt', 'a', encoding='utf-8')
        for k, v in data.items():
            s2 = str(v)
            file.write(k + ' ')
            file.write(s2 + ' ')
            file.write('\n')
        file.close

if __name__ == '__main__':
    # 多页爬取
    for i in range(11):
        urls = {'https://movie.douban.com/top250?start={}&filter='.format(i * 25)}
        # 遍历
        for url in urls:
            get_top(url)

运行结果
注意:因为写入文件时设置的参数是a而不是w,所以每次写入并不会覆盖上一次的结果,会接着上一次的结果重复写入,可以通过在文件名命名时加入time使得每次输出文件名不同。具体应用见作业。
运行结果
txt文件:
txt图片

作业——爬取b站某搜索关键词的的1000个视频数据

代码

#引入库
import requests
from bs4 import BeautifulSoup
import json
import time

#设置hesders反爬虫,还可以在后面加Host参数,但是本次作业中没有用到也可以
headers = {
'User-Agent': 'Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 52.0.2743.116Safari / 537.36Edge / 15.15063'
 }
 

#抓取网址
#以下代码中的网址https://search.bilibili.com/video?keyword=%E5%B1%B1%E6%B2%B3%E4%BB%A4&order=totalrank&duration=0&tids_1=0&page=1
#表示搜索山河令后按综合排序的第一页
#如下示代码,修改page后的数字可以获取不同页的网页代码,依次解析,逐个分析即可获取想要数据。
#(1)若想要限制视频时长,可以修改duration的值,0表示全部时长,1表示10分钟以下,2表示10-30分钟,3表示30-60分钟,4表示60分钟以上。
#(2)若想限制视频分区,可以修改tids_1的值,0表示全部分区,1表示动画,13表示番剧,167表示国创,3表示音乐,129表示舞蹈,4表示游戏,36表示知识,188表示数码,160表示生活,211表示美食,217表示动物,119表示鬼畜,155表示时尚,202表示资讯,5表示娱乐,181表示影视,177表示纪录片,23表示电影,11表示电视剧。
#(3)若想修改排序方式,则修改order的值:
#order=totalrank   综合排序
#order=click        点击量
#order=pubdate      最新发布
#order=dm            弹幕数
#order=stow         收藏量

# 筛选信息
def get_top():
    movie_list = []
    for i in range(0, 50):
     link = 'https://search.bilibili.com/video?keyword=%E5%B1%B1%E6%B2%B3%E4%BB%A4&order=totalrank&duration=0&tids_1=0&page=' + str(i+1) # 共依次得到50页视频的网址
     # print(link)
     r = requests.get(link, headers=headers, timeout=10) #获取网页代码

#通过页响应状态码判断是否抓取正常
     #print(r)
     print(str(i + 1), "页 响 应 状 态 码:", r.status_code)

#美化抓取的网页代码方便解析
     soup = BeautifulSoup(r.text, 'lxml')
          #print(soup)


#抓取关键字段以备后续获取数据
     uptimes = soup.find_all('span', class_='so-icon time') #上传时间
     # print(time)
     #print(time.get_text())
 
     upnames = soup.find_all('a', class_='up-name') #up主
     #for i in range(0, len(upnames)):
     #print(upnames[i].get_text())
 
     titles = soup.find_all('a', class_='title') #视频标题
     #print(titles)
     #for i in range(0, len(titles)):
     # print(titles[i].get_text())
 
     links = soup.find_all('a', class_='title') #视频链接
     #for i in range(0, len(links)):
     # print(links[i].get('href'))
     #print(links.get('herf'))
 
     watch_nums = soup.find_all('span', class_='so-icon watch-num') #播放量
     #for i in range(0, 20):
     # print(watch_nums[i].get_text())
 
     subtitle_numbers = soup.find_all('span', class_='so-icon hide') #弹幕数
 
     #numbers = range(1, 21)
     #pages = range(1, 51)
 
     evaluates = soup.find_all('div', class_='des hide') #简介
 

#引入时钟
#得到时间tim1和tim2。
#tim1作为数据更新时间显示在输出的Txt文件内,%Y %m %d %H %M %S分别表示年月日时分秒要注意这里的%H %M %S之间不能用:连接,用_连接即可。
#tim2用作文件命名,因为获取1000条数据有可能卡时间超过1分钟,所以为了避免输出多个文件,仅取到以时为单位命名即可
     tim1 = time.strftime('%Y-%m-%d %H_%M_%S', time.localtime(time.time()))
     tim2 = time.strftime('%Y-%m-%d %H', time.localtime(time.time()))
 
 
    # 将信息放进字典中
     for uptime, title, upname, link, watch_num, subtitle_number, evaluate in zip(uptimes, titles, upnames, links, watch_nums, subtitle_numbers, evaluates):
         data = {
             #'页数': page,
             #'序号': number,
             '视频名字': title.get_text(),
             'up主': upname.get_text(),
             '链接': link.get('href'),
             '弹幕数': subtitle_number.get_text(),
             '播放量': watch_num.get_text(),
             '上传时间': uptime.get_text(),
             '简介': evaluate.get_text()
         }
         print(data)
         # 写入文件
         fname = 'D:/web_homework_1/' + tim2 + r'result.txt'
         file = open(fname, 'a', encoding="utf-8")
         file.write('****************' + 'tip:以下视频数据更新时间为' + ' ' + tim1 + '**************************')
         file.write('\n\n\n')
         for k, v in data.items():
         s2 = str(v)
         file.write(k + ' ' + ':' + ' ')
         file.write(s2 + ' ')
         file.write('\n')
         file.close

 
     return 0
 
 get_top()
 
 
'''
import time
tim = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
print(tim)
'''

运行结果:

运行结果txt文件:
txt文件

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值