近期,和小伙伴们一起组织了疯狂数据分析小组,通过有计划的输入,每周总结一篇数据类文章,分别投稿到疯狂数据分析专题,并坚持一年时间,具体计划请看零基础入门数据分析成员的新年计划。可是如何管理作业呢?一个一个的去数,这个确实有点麻烦了。哈哈,于是想到爬虫大家的交作业情况,然后每周做个时间筛选就可以了,今天试了下,果然方便多了,那如何来做呢?倒杯水哈,我慢慢给你讲,保准你一听就明白。
阅读路线:
- 一:爬虫目标
- 二:获取索引页内容
- 三:解析索引页
- 四:Ajax异步加载
- 五:获取并解析详情页内容
- 六:结果存入Mysql
小提示:由于同学们是在不断的提交作业,所以大家看到的疯狂数据分析专题主页会和现在的有些区别
一:目标
对于管理小组成员的作业情况,我们需要得到交作业同学的用户名、文章标题、交作业时间、所写内容的字数(防止为了交作业而交作业)。
先大概看下疯狂数据分析专题的首页情况
如果仔细看的话,这里只能得到交作业同学的用户名和标题,那还少两个怎么办呢?我们先点开看下
点开之后,发现我们需要的 用户名、 文章标题、 交作业时间、 所写内容的字数都是有的,很开心。这时,我们先定下爬虫的方案,我是这样操作的:
- 先在疯狂数据分析专题这个页面下,我们称为索引页,得到文章标题和跳到详情页的链接,就是我们刚点开的那个。然后在详情页中再获得用户名、交作业时间、所写内容的字数
二:获取索引页内容
先看下我们的索引页地址
我们开始吧
import requests #这是向发出请求的包
headers = {'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"}
url="https://www.jianshu.com/c/af12635a5aa3"
respones = requests.get(url,headers=headers)
print(respones.text)
关于requests库的使用,请参考这里Request Quickstart。
下面是爬虫得到的HTML结果
对于 HTML,建议大家了解些这方面的知识 HTML Tutorial
如果要看到网页上的 HTML结果,首先 鼠标右键,点击 检查,便会有这样的页面。
如图,想看到某一部分的 HTML内容时,【1】先点击下图片右侧按钮,【2】然后在把鼠标放到左边的任何位置上,【3】便能 HTML中给显示出来
三:解析索引页
import requests
from bs4 import BeautifulSoup
import pymysql
headers = {'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"}
url="https://www.jianshu.com/c/af12635a5aa3"
respones = requests.get(url,headers=headers)
html=respones.text
soup = BeautifulSoup(html, 'html.parser')
note_list = soup.find_all("ul", class_="note-list")[0]
content_li = note_list.find_all("li")
for link in content_li:
url = link.find_all("a", class_="title")[0]
print(url)
关于BeautifulSoup解析库的使用,请参考[Beautiful Soup Documentation]
(https://www.crummy.com/software/BeautifulSoup/bs4/doc/),这里大家暂时掌握住find_all()、get()、content方法便可。
看看我们刚刚解析后的结果
其实这里放出来的是全部的结果,但是只有10条,但是现在已经30篇文章了啊。这是为什么呢?
四:Ajax异步加载
通俗解释下,就是打开某个网页时,是不能看到所有的结果的,但是鼠标下拉时,网页又多了一部分内容,在这个过程之中每次只加载一部分,并没有重新加载整个页面内容的这种情况,就是Ajax异步加载,刚刚我们只得到一部分结果,就是因为这个。大家打开我们的专题-----疯狂数据分析专题,试试看有没有这样神奇的效果。
刚一打开的时候是这样的,
大家鼠标放在左边下滑来看看
这时大家会发现多出了这样的链接
https://www.jianshu.com/c/af12635a5aa3?order_by=added_at&page=2
https://www.jianshu.com/c/af12635a5aa3?order_by=added_at&page=3
https://www.jianshu.com/c/af12635a5aa3?order_by=added_at&page=4
https://www.jianshu.com/c/af12635a5aa3?order_by=added_at&page=5
这些多出来的链接就是我们下拉的时候产生的,并且他们中只是Page后面的参数发生了改变,其实是每增加一页是增加了10篇文章。现在是有42篇文章,我们设置page为5就足够用了(刚刚我们看的时候是30篇,现在同学们开始交作业了,每周日12点交齐本周作业)
现在我们再来看看代码上是如何展示的
import requests
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
import pymysql
headers = {'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"}
def get_page_index(number):
url="https://www.jianshu.com/c/af12635a5aa3?order_by=added_at&page=%s"%number
try:
respones = requests.get(url,headers=headers) # get请求
if respones.status_code == 200:
return respones.text
return None
except RequestException:
print("请求有错误")
return None
def parse_index_page(html):
soup = BeautifulSoup(html, 'html.parser')
note_list = soup.find_all("ul", class_="note-list")[0]
content_li = note_list.find_all("li")
dir={}
for link in content_li:
url = link.find_all("a", class_="title")[0]
title=url.contents[0]
link="https://www.jianshu.com"+url.get("href")
# 因为title 会有重复的情况,但是link是不会重复的,所以写成下面的形式
dir[link]=title
return dir
def main():
for number in range(1,6):
html=get_page_index(number)
dir=parse_index_page(html)
print(dir)
if __name__=="__main__":
main()
这时就可以取出所有的结果了,如下:
五:获取并解析详情页内容
import requests
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
import pymysql
headers = {'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"}
def get_page_index(number):
url="https://www.jianshu.com/c/af12635a5aa3?order_by=added_at&page=%s"%number
try:
respones = requests.get(url,headers=headers) # get请求
if respones.status_code == 200:
return respones.text
return None
except RequestException:
print("请求有错误")
return None
def parse_index_page(html):
soup = BeautifulSoup(html, 'html.parser')
note_list = soup.find_all("ul", class_="note-list")[0]
content_li = note_list.find_all("li")
dir={}
for link in content_li:
url = link.find_all("a", class_="title")[0]
# m=j.content
title=url.contents[0]
link="https://www.jianshu.com"+url.get("href")
# 因为title 会有重复的情况,但是link是不会重复的,所以写成下面的形式
dir[link]=title
return dir
def get_page_detail(url):
try:
respones=requests.get(url,headers=headers)#get请求
if respones.status_code==200:
return respones.text
return None
except RequestException:
print("请求详情页有错误")
return None
def parse_detail_page(title,html):
title=title
soup = BeautifulSoup(html, 'html.parser')
name=soup.find_all("div",class_="info")[0].find_all("span",class_="name")[0].find_all("a")[0].contents[0]
content_detail = soup.find_all("div", class_="info")[0].find_all("div",class_="meta")[0].find_all("span")
content_detail=[info.contents[0] for info in content_detail]
publish_time=content_detail[0]
word_age = content_detail[1]
return title,name,publish_time,word_age
def main():
for number in range(1,6):
html=get_page_index(number)
dir=parse_index_page(html)
for link,title in dir.items():
html=get_page_detail(link)
title, name, publish_time, word_age=parse_detail_page(title, html)
print(title, name, publish_time, word_age)
if __name__=="__main__":
main()
看下结果:
六:结果存入Mysql
import requests
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
import pymysql
headers = {'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"}
def get_page_index(number):
url="https://www.jianshu.com/c/af12635a5aa3?order_by=added_at&page=%s"%number
try:
respones = requests.get(url,headers=headers) # get请求
if respones.status_code == 200:
return respones.text
return None
except RequestException:
print("请求有错误")
return None
def parse_index_page(html):
soup = BeautifulSoup(html, 'html.parser')
note_list = soup.find_all("ul", class_="note-list")[0]
content_li = note_list.find_all("li")
dir={}
for link in content_li:
url = link.find_all("a", class_="title")[0]
# m=j.content
title=url.contents[0]
link="https://www.jianshu.com"+url.get("href")
# 因为title 会有重复的情况,但是link是不会重复的,所以写成下面的形式
dir[link]=title
return dir
def get_page_detail(url):
try:
respones=requests.get(url,headers=headers)#get请求
if respones.status_code==200:
return respones.text
return None
except RequestException:
print("请求详情页有错误")
return None
def parse_detail_page(title,html):
title=title
soup = BeautifulSoup(html, 'html.parser')
name=soup.find_all("div",class_="info")[0].find_all("span",class_="name")[0].find_all("a")[0].contents[0]
content_detail = soup.find_all("div", class_="info")[0].find_all("div",class_="meta")[0].find_all("span")
content_detail=[info.contents[0] for info in content_detail]
publish_time=content_detail[0]
word_age = content_detail[1]
return title,name,publish_time,word_age
def save_to_mysql(title, name, publish_time, word_age):
cur=conn.cursor()
insert_data= "INSERT INTO exercise(name,title,publish_time,word_age)" "VALUES(%s,%s,%s,%s)"
val=(name,title,publish_time,word_age)
cur.execute(insert_data,val)
conn.commit()
conn=pymysql.connect(host="localhost",user="root", password='123456',db='crazydata',port=3306, charset="utf8")
def main():
for number in range(1,6):
html=get_page_index(number)
dir=parse_index_page(html)
for link,title in dir.items():
html=get_page_detail(link)
title, name, publish_time, word_age=parse_detail_page(title, html)
save_to_mysql(title, name, publish_time, word_age)
if __name__=="__main__":
main()
我们到mysql中去看下结果。
建议大家也来实践下,一方面是练习爬虫技能,另一方面可以清楚的看到有多少人在一起努力,他们都是做了哪些事情。过一段时间,再来看下,还有哪些人在坚持,坚持下来的同学们身上发生了哪些变化。2019新的一年,马上要到了,写下我们的计划,一步步的去践行,大家相互见证成长。可以参考python、SQL、统计学、实战组长建议的计划