线程池: 一次性开辟一些线程,我们用户直接给线程池提交任务,线程任务的调度交给线程池来完成
针对使用requests请求返回结果为html类型的网站,我最喜欢使用xpath选择,也就是把返回来的html或者xml文档提交给etree.HTML。
当然,你还可以通过python自带的re库来使用正则表达式提取html文档中你所需要的关键字。
还有一种办法是使用bs4包中的BeautifulSoup方法,同样也可以提取到相关的内容。
关键代码如下所示:
'''
使用多线程下载一篇478.7万小说
'''
def get_down_url(url):
html = etree.HTML(requests.get(url).text)
filename = html.xpath('/html/body/div[3]/div[1]/h1/text()')[0]
if not os.path.exists(filename):
os.mkdir(filename)
# 获取所有的div
div_list = html.xpath('/html/body/div[3]/div[2]/div[2]/div')
# 使用线程池下载
with ThreadPoolExecutor(1000) as t:
for child_list in div_list:
# 获取每个div的名字,方便给文件夹命名
child_filename = child_list.xpath('./div/text()')[3].replace(' ', '_')
# 获取每个列表中的url
child_ul = child_list.xpath('./ul/li/a/@href')
# print(child_ul)
for x in range(len(child_ul)):
if not os.path.exists(filename + '/' + child_filename):
os.mkdir(filename + '/' + child_filename)
t.submit(download, child_ul[x], filename, child_filename)
# 普通模式下载,数度极慢
# download(child_ul[x],filename,child_filename)
def download(url, filename, child_filename):
html = etree.HTML(requests.get(url).text)
# 获取小说章节的名称
title_filename = html.xpath('/html/body/div[2]/div[3]/div[3]/div/div[1]/div[2]/div[2]/text()')[0]
# 获取小说内容
content = html.xpath('/html/body/div[2]/div[3]/div[3]/div/div[1]/div[5]/p/text()')
# 在对应部分下创建对应名称的txt文档
f = open(filename + '/' + child_filename + '/' + title_filename + '.txt', 'w', encoding='utf-8')
for c in content:
f.write(c + '\n')
print(f'{child_filename}{title_filename}下载完毕!!!')
def main():
t1 = time.time()
# 调用下载的函数,采用base64解码加密后的网站
get_down_url(str(base64.b64decode('aHR0cDovL2Jvb2suem9uZ2hlbmcuY29tL3Nob3djaGFwdGVyLzEwODU5OTkuaHRtbA=='))[1:].replace("'",""))
print(f'下载完成!一共耗时:{time.time() - t1} 秒!!')
if __name__ == '__main__':
main()
"""
xpath基础:
<div>
<div>
<span>aaa</span>
<p>
<span>bbb</span>
</P>
<div>
<p>
<span>ccc</span>
</P>
</div>
# 表示div[1]下所有子类为span的值
num = x.xpath('./div[1]//span/text()')
输出,aaa,bbb,ccc
# 表示div[1]任意下一级后的下一级为span的值
num = x.xpath('./div[1]/*/span/text()')
输出 aaa,ccc
"""
线程池的下载数度还不是最快的,使用协程下载才能达到最快,而且下载数度还和电脑配置有关系,反正我的电脑需要用15s多钟,我试了一下使用云服务器的配置,只需要4s钟。
有兴趣的小伙拍可以尝试使用协程下载,我也在研究如何使用协程下载
补充一个关于bs4ku使用的小案例
# 安装
# Pip install bs4 -i 清华大学镜像下载链接
import csv
import os
from bs4 import BeautifulSoup
import requests
def base_bs4(url="http://www.shucai123.com/price/"):
resp = requests.get(url)
# print(resp.text)
# 解析数据
# 1.把页面源代码交给BeautifuSoup进行处理,生成bs对象
page = BeautifulSoup(resp.text, "html.parser") # 指定html解析器
# 2.从bs对象中查找数据
# find(标签,属性=值)
# find_all(标签,属性=值)
# table = page.find("table", class_="bjtbl") # class是python的关键字
table = page.find("table", attrs={"class": "bjtbl"}) # 和上面效果一样
# print(table)
# 拿出所有数据行
trs = table.find_all("tr")[1:]
for tr in trs: # 每一行数据
tds = tr.find_all("td") # 拿到每行中的所有td
time = tds[0].text # .text 表示拿到被标签标记的内容
origin = tds[1].text
sort = tds[2].text
pz = tds[3].text
tel_name = tds[4].text
# print(time,origin,sort,pz,tel_name)
csvwriter.writerow([time, origin, sort, pz, tel_name])
print("{}数据爬取完毕!".format(url))
print('')
if __name__ == '__main__':
if os.path.exists("菜价.csv"):
os.remove("菜价.csv")
f = open('菜价.csv', 'w', encoding='utf-8')
csvwriter = csv.writer(f)
for x in range(1, 5000):
url = "http://www.shucai123.com/price/t" + str(x)
base_bs4(url)
f.close()
源代码以及更多爬虫实战案例gitee下载地址