新手上路,歡迎批評。博客暫時只爲記錄學習過程。
抓取結果:
整體思路:
1.鏈接數據庫並建好一張表。要存儲以下信息,問題,回答者,回答時間,回答內容。
def createtable():
# 打開數據庫連接
db = pymysql.connect("localhost","root","sql123","likelearn", charset='utf8' )
# 使用 cursor() 方法創建一個遊標對象 cursor
cursor = db.cursor()
# 使用 execute() 方法執行 SQL,如果表存在則刪除
cursor.execute("DROP TABLE IF EXISTS goodAnswer")
# 使用預處理語句創建表
sql = """CREATE TABLE goodAnswer(
question text not null,
a_name varchar(20) not null,
a_time varchar(20) not null,
a_content text not null) CHARSET=utf8 """
cursor.execute(sql)
# 關閉數據庫連接
db.close()
2.抓取一個問題彙總頁面 http://iask.sina.com.cn/c/74-goodAnswer-1-new.html 寫一個函數geturls()獲取該頁面上指向其他問題彙總頁面的鏈接,存儲在全局變量 pageurls 中。
註釋掉的最後一行,是遞歸抓取整個100頁的所有問題彙總頁面的鏈接,這裏我只抓取了1,2,3,100這四個頁面。
def geturls(url):
global pageurls
url = "http://iask.sina.com.cn/" + str(url)
print(url)
req = getpage(url)
soup = BeautifulSoup(req.text,"html.parser")
hrefs = soup.find("div",{"class":"page mt30"}).find_all("a")
for pageurl in hrefs:
if "href" in pageurl.attrs:
if pageurl["href"] not in pageurls:
pageurls.append(pageurl["href"])
# geturls(pageurl["href"])
3.兩層循環,第一層循環變量pageurls,每次獲得一個問題彙總頁面,並且用函數 getlinks() 獲得該頁面上的所有具體問題的鏈接。
第二層抓取具體問題回答的頁面,並且用函數 getdetail() 獲得最好回答的的各個字段。
# 獲取頁面的所有問題鏈接
def getlinks(soup):
temp = soup.find_all("div",{"class":"question-title"})
links = []
for link in temp:
links.append(link.a["href"])
return links
# 獲取問題的回答者,回答時間回答內容
def getdetail(soup):
item = []
#獲取回答者的名字
a_name = soup.find("div", {"class":"answer_tip"})
if a_name == None:
a_name = " "
else:
a_name = a_name.a
#獲取回答時間
a_time = soup.find("div", {"class":"answer_tip"})
if a_time == None:
a_time = " "
else:
a_time = a_time.span
#獲取回答內容
a_content = soup.find("div",{"class":"answer_text"})
if a_content == None:
a_content = " "
elif soup.find("div",{"class":"answer_text"}).find("div",{"style":"display: none"}) == None:
a_content = soup.find("div",{"class":"answer_text"})
else:
a_content = soup.find("div",{"class":"answer_text"}).find("div",{"style":"display: none"})
ques = soup.find("div", {"class":"question_text"})
item.append(tool(ques))
item.append(tool(a_name) )
item.append(tool(a_time) )
item.append(tool(a_content) )
return item
4. 鏈接數據庫,將抓取到的各個字段存儲在已經建好的表 goodAnswer 中。
插入方法參考: http://www.runoob.com/python3/python3-mysql.html
以下是全部代碼:
# -*- coding:utf-8 -*-
import requests
from bs4 import BeautifulSoup
import re
import pymysql
import time
# 用來存儲頁面的url
pageurls = []
# 獲取一個頁面
def getpage(url):
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
req = requests.get(url, headers = headers)
if req.status_code == 200:
pass
else:
print("獲取失敗,請檢查URL:", url)
return req
# 獲取頁面的所有問題鏈接
def getlinks(soup):
temp = soup.find_all("div",{"class":"question-title"})
links = []
for link in temp:
links.append(link.a["href"])
return links
# 獲取所有的頁面鏈接
def geturls(url):
global pageurls
url = "http://iask.sina.com.cn/" + str(url)
print(url)
req = getpage(url)
soup = BeautifulSoup(req.text,"html.parser")
hrefs = soup.find("div",{"class":"page mt30"}).find_all("a")
for pageurl in hrefs:
if "href" in pageurl.attrs:
if pageurl["href"] not in pageurls:
pageurls.append(pageurl["href"])
# geturls(pageurl["href"])
# 獲取問題的回答者,回答時間回答內容
def getdetail(soup):
item = []
#獲取回答者的名字
a_name = soup.find("div", {"class":"answer_tip"})
if a_name == None:
a_name = " "
else:
a_name = a_name.a
#獲取回答時間
a_time = soup.find("div", {"class":"answer_tip"})
if a_time == None:
a_time = " "
else:
a_time = a_time.span
#獲取回答內容
a_content = soup.find("div",{"class":"answer_text"})
if a_content == None:
a_content = " "
elif soup.find("div",{"class":"answer_text"}).find("div",{"style":"display: none"}) == None:
a_content = soup.find("div",{"class":"answer_text"})
else:
a_content = soup.find("div",{"class":"answer_text"}).find("div",{"style":"display: none"})
ques = soup.find("div", {"class":"question_text"})
item.append(tool(ques))
item.append(tool(a_name) )
item.append(tool(a_time) )
item.append(tool(a_content) )
return item
# 清理不必要的標籤和特殊符號
def tool(x):
x = str(x)
replaceBR = re.compile('<pre>|</pre>')
removeImg = re.compile('<span.*?>|</span>" "*?|</span>')
replaceLine = re.compile('<div.*?>|</div>')
removeAddr = re.compile('<a.*?>|</a>')
removespace = re.compile('\s*')
removete = re.compile('\W')
x = re.sub(replaceBR,"",x)
x = re.sub(removeImg,"",x)
x = re.sub(replaceLine,"",x)
x = re.sub(removeAddr,"",x)
x = re.sub(removespace,"",x)
x = re.sub(removete,"",x)
return x
def createtable():
# 打開數據庫連接
db = pymysql.connect("localhost","root","sql123","likelearn", charset='utf8' )
# 使用 cursor() 方法創建一個遊標對象 cursor
cursor = db.cursor()
# 使用 execute() 方法執行 SQL,如果表存在則刪除
cursor.execute("DROP TABLE IF EXISTS goodAnswer")
# 使用預處理語句創建表
sql = """CREATE TABLE goodAnswer(
question text not null,
a_name varchar(20) not null,
a_time varchar(20) not null,
a_content text not null) CHARSET=utf8 """
cursor.execute(sql)
# 關閉數據庫連接
db.close()
# 邏輯控制主函數
def main():
# 鏈接數據庫操作數據庫
db = pymysql.connect("localhost","root","sql123","likelearn", charset='utf8')
# 使用 cursor() 方法創建一個遊標對象 cursor
cursor = db.cursor()
# 爲了簡潔我只抓取第 1 2 3 100 這四個頁面的 url
geturls("/c/74-goodAnswer-1-new.html")
# 遍歷四個 url 抓取頁面
for url in pageurls:
page = getpage("http://iask.sina.com.cn" + str(url))
soup = BeautifulSoup(page.text,"html.parser")
print("獲得該頁面所有問題的鏈接", "http://iask.sina.com.cn" + str(url))
links = getlinks(soup)
# 遍歷每個該頁面的所有問題鏈接
for link in links:
print("獲得goodAnswer頁面詳情",link)
a_page = getpage("http://iask.sina.com.cn/" + str(link))
a_soup = BeautifulSoup(a_page.text, "html.parser")
print("獲得問題最好回答的各個信息段")
a_item = getdetail(a_soup)
# #SQL 插入語句
sql = "INSERT INTO goodAnswer(question, a_name, a_time, a_content)VALUES ('%s', '%s', '%s', '%s')"%(a_item[0], a_item[1], a_item[2],a_item[3])
try:
print("# 執行 sql 語句")
cursor.execute(sql)
print("# 提交到數據庫執行")
db.commit()
except:
print("# 發生錯誤回滾")
db.rollback()
time.sleep(2)
# 關閉數據庫連接
db.close()
createtable()
main()