计网大作业-web应用之爬虫

计算机通信与网络课外实验

作者:周洪锋2000920**** 刘勇建2000920****

实验题目

WEB应用——利用爬虫爬取”电影天堂“网站的电影

实验目的

  • 通过爬虫工具的使用,加强对HTTP协议的理解
  • 学会如何发送请求头,完成与HTTP服务器的交互
  • 在解析页面的过程中熟悉HTML 代码

实验工具

  • python(装有requestbs4等模块)
  • chrome浏览器

实验原理

HTTP协议

HTTP协议是面向事务的应用层协议,可以完成超文本内容的传送。其基本过程如下图所示:服务器不断在80端口监听是否有客户端浏览器的请求,一旦监听到请求后,便由客户端发起TCP连接的建立。随后浏览器向客户机发送HTTP请求报文,申请获取指定URL的页面,服务器收到请求后,便向客户机发送对应的页面(通常是HTML代码,后由浏览器解析)。

HTTP协议基本原理

HTTP协议有以下特点

  • HTTP是无状态的。浏览器不会记得曾经访问过的客户,也不会记录客户的信息。但是,Cookies技术可以改变这一特点。
  • HTTP的请求报文头使用ASCII码,是可读的。用户可以检查浏览器发出的请求头和收到的响应头来获得相应信息(本实验中,使用请求头的User-Agent信息来伪装请求报文。同时响应头中含有状态码,可以用于查看服务器的响应情况。
  • HTTP使用HTML(超文本标记语言)作为制作页面的语言。可以使用Python的相关模块对HTML进行解析,提取其中的信息。

请求头的格式

爬虫原理

正常的HTTP访问请求中,由浏览器发送请求报文,而爬虫便是使用Python等工具向服务器发送大量请求报文,批量获取服务器的响应,并从中获取有效信息。

在爬取之前,需要了解目标网站的网址、网页结构、是否有反爬虫机制等相关信息。

实验步骤

1、分析网站结构

通过在chrome浏览器中对网页进行检查,可以发现,在网站的 电影->最新电影->下载页面 中有规律地列出了许多最新电影的下载页面,可以从该页面电影天堂开始作为爬取的对象。

查看网页的HTML代码,可以发现下载跳转链接都被放在一个<div class='bd3r'>标签中,可以使用网页解析工具对该页面进行解析,抽取出想要的电影信息。

当然,一页的电影肯定是不够的,需要考虑下载多个页面的内容,不难发现,该网站不同页的url有以下的规律

1
2
3
https://www.dy2018.com/html/gndy/dyzz/index.html //第一页
https://www.dy2018.com/html/gndy/dyzz/index_2.html //第二页
https://www.dy2018.com/html/gndy/dyzz/index_3.html //第三页

这样,我们就可以简单推出所有页面的url。

2、发出HTTP请求

python3中带有requests模块,其中的get()函数可以自动向HTTP服务器发出请求,可以通过以下的调用发出请求

1
2
url = "https://www.dy2018.com/html/gndy/dyzz/index.html"
requests.get(url)

但是,检查返回的状态码会发现,HTTP并没有给出正确的响应,因为requests.get()发出的请求被服务器识别为不正常的请求,为了让服务器能够正常响应,需要伪装请求头。打开浏览器的检查,通过抓包可以查看浏览器发出的请求头信息:

请求头信息

user-agent代表的是客户端浏览器的相关信息,为了防止服务器拒绝我们的请求,可以在调用get函数时携带headers参数,来伪装成是浏览器发出的请求,同时还可以设置cookies来保持登录状态。

以下为获得HTTP响应的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def GetHtml(url):
ua = UserAgent()
headers={
'user-agent':str(ua.random),
'Connection':'close'
}

r = requests.get(url,headers=headers)

if r.status_code == 200:
r.encoding = 'gb2312'
soup = BeautifulSoup(r.text,'lxml') //使用bs4模块对获取的页面解析
else:
return None
return soup

3、页面解析、信息提取

再次检查页面,可以发现每一部电影的链接都置于标签<a class='ulink'>中,可以考虑使用BeautifulSoup模块抽取出页面每一个class为ulink的标签,进行进一步解析。

提取出的标签含有较多无用信息,可以考虑对标签中的信息进一步清洗。

  • 电影的标题考虑使用正则表达式来匹配书名号中的内容
  • 电影详细页面的链接可以使用BeautifulSoup来提取出标签中的href
1
2
3
4
5
6
7
8
9
10
11
12
def Parser(soup):
raw = soup.find_all("a",class_='ulink')
ptn = re.compile(r"《[\u4e00-\u9fa5]*》")
movies = []
urls = []
for each in raw:
movies.extend(ptn.findall(each.string))
urls.append(each["href"])
full_urls = []
for url in urls:
full_urls.append(parse.urljoin(root_url,url))
return movies,full_urls

这样,就可以爬取出电影和电影的详细页面,但是还无法获得下载电影的磁力链接。电影磁力链接在详细页面中可以找到,所以可以通过上一步获得的详细页面链接,尝试访问详细信息页面,用类似的方法(正则表达式)提取出电影的磁力链接。

1
2
3
4
5
6
7
8
9
10
11
def SubHtml(urls):
magnet = []
for url in urls:
soup = GetHtml(url)
if soup == None:
continue
get = soup.find("a",href=re.compile(r'magnet(.*?\.mp4)?'))
if get != None:
magnet.append(get.string)
print(get.string)
return magnet

4、开始爬取

整个爬虫程序的流程图如下所示:

实验结果

将爬取到的信息储存到txt文本文档中,结果如下所示:

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import re
from sre_constants import AT
from bs4 import BeautifulSoup
from selenium import webdriver
import requests
from urllib import parse
import time
from requests.adapters import HTTPAdapter
from fake_useragent import UserAgent

def GetHtml(url):
ua = UserAgent()
headers={
'user-agent':str(ua.random), //使用随机UA,防止被服务器拒绝
'Connection':'close'
}

r = requests.get(url,headers=headers)

if r.status_code == 200:
r.encoding = 'gb2312'
soup = BeautifulSoup(r.text,'lxml')
else:
return None
#print(r.text)
return soup

def Parser(soup):
raw = soup.find_all("a",class_='ulink')
#print(raw)
ptn = re.compile(r"《[\u4e00-\u9fa5]*》")
movies = []
urls = []
for each in raw:
movies.extend(ptn.findall(each.string))
urls.append(each["href"])
#print(movies)
#print(urls)
full_urls = []
for url in urls:
full_urls.append(parse.urljoin(root_url,url))
return movies,full_urls

def Save(movies,urls,magnets):
with open(r"D:\AAA桌面映射文档\抢课app\爬虫\text.txt","a+",encoding='utf-8') as fp:
for m,u,magnet in zip(movies,urls,magnets):
fp.write(m+'\n')
fp.write(u+'\n')
fp.write(magnet+'\n')


def SubHtml(urls):
magnet = []
for url in urls:
soup = GetHtml(url)
if soup == None:
continue
#print(soup)
get = soup.find("a",href=re.compile(r'magnet(.*?\.mp4)?'))
if get != None:
magnet.append(get.string)
print(get.string)
#print(get.string)
return magnet


if __name__ == "__main__":
root_url = "https://www.dy2018.com/html/gndy/dyzz/index.html"
soup = GetHtml(root_url)
movies,urls = Parser(soup)
magnets = SubHtml(urls)
Save(movies,urls,magnets)

for i in range(2,6):
root_url = "https://www.dy2018.com/html/gndy/dyzz/index_{0}.html".format(str(i))
soup = GetHtml(root_url)
movies,urls = Parser(soup)
magnets = SubHtml(urls)
#print(magnets)
Save(movies,urls,magnets)


计网大作业-web应用之爬虫
http://zhouhf.top/2022/06/07/计网大作业-web应用之爬虫/
作者
周洪锋
发布于
2022年6月7日
许可协议