写在前面
最近想找几本电子书看看, 就翻啊翻, 然后呢, 找到了一个 叫做 周读的网站 , 网站特别好, 简单清爽, 书籍很多, 而且打开都是百度网盘可以直接下载, 更新速度也还可以, 于是乎, 我给爬了. 本篇文章学习即可, 这么好的分享网站, 尽量不要去爬, 影响人家访问速度就不好了 http://www.ireadweek.com/ , 想要数据的, 可以在我博客下面评论, 我发给你, QQ, 邮箱, 啥的都可以.
这个网站页面逻辑特别简单 , 我翻了翻 书籍详情页面 , 就是下面这个样子的, 我们只需要循环生成这些页面的链接, 然后去爬就可以了, 为了速度, 我采用的多线程, 你试试就可以了, 想要爬取之后的数据, 就在本篇博客下面评论, 不要搞坏别人服务器.
- http://www.ireadweek.com/index.php/bookInfo/11393.html
- http://www.ireadweek.com/index.php/bookInfo/11.html
- ....
撸代码
代码非常简单, 有咱们前面的教程做铺垫, 很少的代码就可以实现完整的功能了, 最后把采集到的内容写到 CSV 文件里面,(CSV 是啥, 你百度一下就知道了) 这段代码是 IO 密集操作 我们采用 aiohttp 模块编写.
第 1 步
拼接 URL, 开启线程.
- import requests
- # 导入协程模块
- import asyncio
- import aiohttp
- headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) ApplewebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
- "Host": "www.ireadweek.com",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"}
- async def get_content(url):
- print("正在操作:{}".format(url))
- # 创建一个 session 去获取数据
- async with aiohttp.ClientSession() as session:
- async with session.get(url,headers=headers,timeout=3) as res:
- if res.status == 200:
- source = await res.text() # 等待获取文本
- print(source)
- if __name__ == '__main__':
- url_format = "http://www.ireadweek.com/index.php/bookInfo/{}.html"
- full_urllist = [url_format.format(i) for i in range(1,11394)] # 11394
- loop = asyncio.get_event_loop()
- tasks = [get_content(url) for url in full_urllist]
- results = loop.run_until_complete(asyncio.wait(tasks))
上面的代码可以同步开启 N 多个线程, 但是这样子很容易造成别人的服务器瘫痪, 所以, 我们必须要限制一下并发次数, 下面的代码, 你自己尝试放到指定的位置吧.
- sema = asyncio.Semaphore(5)
- # 为避免爬虫一次性请求次数太多, 控制一下
- async def x_get_source(url):
- with(await sema):
- await get_content(url)
第 2 步
处理抓取到的网页源码, 提取我们想要的元素, 我新增了一个方法, 采用 lxml 进行数据提取.
- def async_content(tree):
- title = tree.xpath("//div[@class='hanghang-za-title']")[0].text
- # 如果页面没有信息, 直接返回即可
- if title == '':
- return
- else:
- try:
- description = tree.xpath("//div[@class='hanghang-shu-content-font']")
- author = description[0].xpath("p[1]/text()")[0].replace("作者:","") if description[0].xpath("p[1]/text()")[0] is not None else None
- cate = description[0].xpath("p[2]/text()")[0].replace("分类:","") if description[0].xpath("p[2]/text()")[0] is not None else None
- douban = description[0].xpath("p[3]/text()")[0].replace("豆瓣评分:","") if description[0].xpath("p[3]/text()")[0] is not None else None
- # 这部分内容不明确, 不做记录
- #des = description[0].xpath("p[5]/text()")[0] if description[0].xpath("p[5]/text()")[0] is not None else None
- download = tree.xpath("//a[@class='downloads']")
- except Exception as e:
- print(title)
- return
- ls = [
- title,author,cate,douban,download[0].get('href')
- ]
- return ls
第 3 步
数据格式化之后, 保存到 CSV 文件, 收工!
- print(data)
- with open('hang.csv', 'a+', encoding='utf-8') as fw:
- writer = CSV.writer(fw)
- writer.writerow(data)
- print("插入成功!")
运行代码, 查看结果
因为这个可能涉及到获取别人服务器重要数据了, 代码不上传 GitHub 了, 有需要的留言吧, 我单独发送给你
来源: https://www.cnblogs.com/happymeng/p/10172111.html