【Python】爬取某资源站的个人经验分享
本帖最后由 ARtcgb 于 2021-4-23 12:46 编辑就在前两天我爬取某网站的过程中,被一个小小的问题卡住了,经过一段时间的探究也算是攻克了这个问题,现在把一些个人经验分享给大家。
前段时间的爬取给站长带来了极大的不便,所以这个网站暂时不公布给大家了,学习技术为先,爬虫也要适度。
## 爬虫思路
这个网站是属于比较传统的下载站的网站布局。
先来看主页面,网址为正常的https://www.xxxxx.com.cn/ ,页面里也有几个比较关键的信息,我们来研究一下。
从右侧的HTML标签我们也是可以看见这类标题链接点进去是直接跳转到一个/post/xxxx.html 的页面的,这段链接前面也自然是这个网站链接,整体链接就是这个样子的:www.xxxx.com.cn/post/xxxx.html ,这里面后半段的xxxx是四位数字,我猜想,这四位数字的变换对应着不同的界面,我们来实践验证一下。
果不其然,这样就很容易明确该怎么爬取这个网站了。
## 获取所需的子页面链接
根据刚才的经验,我们知道子页面的链接格式,改变的只有其中四位数字,那我们只需要找到数字的规律就可以了。这里我选择直接找到这个网页最早的资源链接,发现最小的页面数字为22.html ,往上则都是连续的,23、24、25···这好办,直接一个for循环走起。
其实还有个更好的解决方法,在这个网站的目录界面找到所有符合我们要求的a标签的href值即可,用哪种方法就看个人所需了。
如果采用第二种方法,这里就要使用BeautifulSoup库,解析页面中所有的`<a rel="bookmark">`并获取里面的href值。这里直接几行代码搞定。
```Python3
import requests
from bs4 import BeautifulSoup
url ="已隐藏"
r_url = requests.get(url)
b_url = BeautifulSoup(r_url.text, 'lxml')
url_list = []
for soup in b_url.find_all('a', rel="bookmark"):
url_list.append(soup['href'])
print(url_list)
```
这里注意findall是返回一个列表,所以提取href时要用上for循环提取列表中每一项的href,否则会报错`TypeError: list indices must be integers or slices, not str`
这里一开始我也疯狂出错,报`KeyError`我一看也找不出错哪里了,最后我一不懂编程的朋友看了下,原来我把href写成herf了。。。。
写爬虫遇见问题时有些快速解决问题的方法,其中就是直接把报错信息放到搜索引擎里面去搜,不推荐百度,国内大部分资源都太水、太难检索,这里点名CSDN,全是重复发文的,一个错全部错,污染环境!
有条件的建议去Google、Stack Overflow上去搜索,一般的问题都不用提问就已经有回复了。
## 获取子页面内容
子页面简单的静态界面解析就不多说了,很简单,BeautifulSoup就能搞定,我们来获取其中需要请求才能获得的内容。
首先打开Network选项卡刷新界面看看,结果发现XHR和JS里面没有什么我们用得上的信息。爬虫就盯着这两个看就行了,这两个里面传递的一般都是关键信息。
这里点击下界面的请求解压密码,结果提示我们需要登录,那就登陆下看看。登陆之后请求到了解压密码,看看network里面的反应。
这样我们就能拿到这个获取密码的网址了,很轻松,我们复制下这个链接打开看看。https://www.xxxx.com.cn/user/jieyamima ,唉?打开之后里面没有任何信息,这怎么办?network里面可是有东西的啊?
我回到preview里面一看,哦,原来是他的request模式不一样,我们用网站访问是post请求,输入到地址栏是get请求,服务器不知道我们要什么的密码,自然就是刚才那个样子了,这里我们用requests的post方法,在请求的时候附带文章id就可以了。
这里推荐一个[工具](https://curl.trillworks.com/#),我们只需要从network选项卡里选择我们需要的包,右键点击,选择copy->copy all as cURL, 然后复制到这个网站里面,选择自己用的语言,就可以自动生成我们请求需要的header,像post请求,它也可以自动判断。下面是他为我生成的例子,隐私的cookie部分已经去除。
```Python3
import requests
headers = {
'authority': 'www.xxxx.com.cn',
'sec-ch-ua': '"Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"',
'accept': 'application/json, text/javascript, */*; q=0.01',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36',
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'origin': 'https://www.xxxx.com.cn',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://www.xxxx.com.cn/post/6138.html',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
'cookie': 'xxxxxxxxxxxxx',
'sec-gpc': '1',
'dnt': '1',
}
data = {
'post_id': '6138'
}
response = requests.post('https://www.xxxx.com.cn/user/jieyamima', headers=headers, data=data)
```
根据我们的需求,我们只需要把我们请求到的文章id替换这个post id我们就可以获取到网站所有的解压密码,十分的方便。请求下来的数据也可以自行留存或是做些别的什么。
## 源代码(参考价值不高)
```Python3
import requests
from bs4 import BeautifulSoup
import time
import re
import xlwt
workbook = xlwt.Workbook(encoding='utf-8')
worksheet = workbook.add_sheet('xxxx')
href_list = []
count = 1
headers = {
'authority': 'www.xxxx.com.cn',
'sec-ch-ua': '"Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"',
'accept': 'application/json, text/javascript, */*; q=0.01',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36',
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'origin': 'https://www.xxxx.com.cn',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://www.xxxx.com.cn/post/6138.html',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
'cookie': 'xxxxxxxxxxxxx',
'sec-gpc': '1',
'dnt': '1',
}
for page_num in range(1, 10):
link = "https://www.xxxx.com.cn/?page=" + str(page_num)
requests_link = requests.get(link)
time.sleep(1)
soup_link = BeautifulSoup(requests_link.text, 'lxml')
for soup in soup_link.find_all("a", rel="bookmark"):
href_list.append(soup.attrs["href"])
print("已添加", str(count), "个链接")
count += 1
line = 0
worksheet.write(line, 0, label="标题")
worksheet.write(line, 1, label="下载链接")
worksheet.write(line, 2, label="解压密码")
for true_href in href_list:
try:
line += 1
number = re.findall("\d+", true_href)
data = {'post_id': number}
url = "https://www.xxxx.com.cn/" + true_href
requests_url = requests.get(url)
soup_url = BeautifulSoup(requests_url.text, 'lxml')
title_url = soup_url.find("h1").text
download_url = soup_url.find("a", class_="btn btn-primary download-popup btn_down").attrs['href']
time.sleep(1)
rl = requests.post("https://www.xxxx.com.cn/user/jieyamima", headers=headers, data=data)
password = BeautifulSoup(rl.text, 'lxml').find("p").text.replace('{"status":1,"msg":"解压密码:', "")
print('标题:', title_url, '\n下载链接:', download_url, '\n解压密码', password, '\n')
worksheet.write(line, 0, label=title_url)
worksheet.write(line, 1, label=download_url)
worksheet.write(line, 2, label=password)
workbook.save('xxxx资源汇总.xls')
except:
pass
``` 本帖最后由 ARtcgb 于 2021-4-24 19:11 编辑
氵怪 发表于 2021-4-24 18:58
初学,这样写的下载内容图片打不开,我的headers就是uesr-agent的内容,楼主指点一下
headers里面不要只放ua,检查里看请求到的资源头部,复制请求资源的cURL到这个链接里面可以直接拿到headers,https://curl.trillworks.com/
另外BS的解析器换成lxml,html.parser请求图片好像不行。 氵怪 发表于 2021-4-24 08:45
链接:https://www.vmgirls.com/15976.html。里面的图片的src加https:以后没法打开。
直接用浏览器当然打不开,用requests加上headers,headers里面放你自己在网页上的请求就行,这图不用你看见,直接requests然后写入content就行 正好能用上的 本帖最后由 caiiiac 于 2021-4-23 14:10 编辑
python 基础已看,正好学习一下 谢谢分享!学习一下。 最近也在学Python 学习学习 正在学习 研究研究 楼主问一下,为什么爬虫下载的图片打不开,图片的src链接也打不开?
氵怪 发表于 2021-4-23 16:03
楼主问一下,为什么爬虫下载的图片打不开,图片的src链接也打不开?
你这问题问的真的一言难尽。。。
具体情况一样没说,这可能性多了去了,爬到的链接对不对,图片是不是被加过密,CSS、JS都可能背锅,你爬的什么网站,啥图片你得列出来啊。
页:
[1]
2