鉴于论文的发表越来越需要新颖的数据,因此如何从网络中直接爬取数据、搭建自己的数据库,是走向学(头)术(发)辉(稀)煌(疏)的必经之路。
本文希望能够将人民日报的数据爬取下来,并且存在MySQL数据库中。因此本文突出讲解如何在局域网中使用MySQL的知识。假设大家已经了解"requests"、"dom"以及"xpath"的python知识。
本人是文科生,尽量使用"文科生"的词汇去描述我要做的事情。。图1:总体流程
1. 别人的电脑如访问将我的笔记本上的MySQL?
1.1 同一个局域网的电脑互相访问mysql数据库
在请教了信息学院的同学之后,我了解到,MySQL允许同一个局域网中的电脑相互访问数据库。在学校里面使用校园无线网、并且只能够通过校园网才能够访问人民日报数据库的情况下,我选择“同一个局域网”允许别的电脑访问我的笔记本MySQL数据库的情形进行分析。
1.2 修改MySQL数据库的访问权限第一步,找到自己笔记本电脑安装MySQL的文件夹,....\MySQL Server 8.0\bin中的mysql.exe。图2:MySQL在电脑中的位置第二步,把....\MySQL Server 8.0\bin放到环境变量中的系统变量的path中。
图3:将路径添加到环境变量的系统变量的path
图3:将路径添加到环境变量的系统变量的path第三步,打开cmd,进入mysql修改权限:
C:\Users\dell>mysql -u root -p
Enter password: *********
mysql> use mysql;
输出:Database changed
mysql> update user set host = '%' where user = 'root';
输出:Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> flush privileges;
输出:Query OK, 0 rows affected (0.01 sec)
——————————————————————————————————————
那么通过以上修改,同一个局域网(WiFi)的电脑均能够通过主机名+密码访问我的笔记本的MySQL数据库。
1.3 查看个人笔记本电脑的IPv4地址
在cmd中输入
ipconfig/all
结果如下图4:查看IPv4
1.4 测试同一个局域网的电脑能否访问我的数据库
首先,在我自己的笔记本中通过Navicat创建一个主机名是IPv4的数据库,主机那里填写IPv4的地址,密码(绿框)自己创建一个(别忘记,下面还要用到密码)。连接名随意填写(我写的是“人民日报”)。端口一般写“3306”,用户名一般写“root”。图5:在个人电脑中的Navicat创建MySQL数据库
然后,可以看一下自己数据库中有一个叫“人民日报”的数据库,注意到“人民日报”和上面的“huatai”的数据库一致,这是因为,新建的“人民日报”就是自己的电脑中的数据库,仅仅是主机名不同(huatai数据库的主机名是“localhost”,而“人民日报”的数据库的主机名是自己电脑的IPv4的地址),因此两者的内容一致。图6:新建“人民日报”数据库的样子
然后,用另一台安装了“Navicat”(不用安装MySQL)电脑,测试能不能连接到我个人笔记本的数据库。以下图片是在另一个电脑、连接相同的WiFi的画面。
在另一台电脑的Navicat中创建新的连接。连接名依然随意写(我写的是dell)。主机名(红框)和我的笔记本电脑一致的IPv4,端口和用户名一样,密码暂时不写。图7:同一个WiFi下的另一台电脑的测试
然后,点击这个新建的数据库,写入密码,此处密码和自己笔记本的MySQL这个数据库的密码一致。即为在图5中的绿框中的密码。
最后,另外一台电脑可以连接我的笔记本的mysql,即便这台电脑没有装mysql。图8:另一台电脑成功访问我的笔记本的MySQL数据库
最后,在自己的笔记本中创建一个叫做“newspaper”的sheet,然后定义好变量。从而为接下来的爬虫程序做好准备。
2. 多线程爬虫程序(简单带过)
import threading
from queue import Queue
import requests
import pandas as pd
from lxml import etree
import glob
import time
from sqlalchemy import create_engine
from sqlalchemy.types import VARCHAR
import pymysql
from pathlib import Path
pymysql.install_as_MySQLdb()
# 通过parse,输入一条链接,输出一个df。
def get_title_content(date, page, link, html):
"""通过把date,page,link以及html传入进去,将html经过dom结构解析,得到title以及content,然后将完整的信息[date,page,link, title, content]作为df输出。"""
dom = etree.HTML(html)
title = dom.xpath(你自己的dom结构解析)
content = dom.xpath(你自己的dom结构解析)
df = pd.DataFrame([date, page, link, title, content],
index=['date', 'page', 'link', 'title', 'content']).T
df.set_index(['link'],inplace=True)
return df
def parse(date, page, link):
"""通过将excel中收集到的信息“Date,page 以及link"传入,和上面的函数联用,输出得到df。"""
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"}
html = requests.get(link, headers=headers).content
html = html.decode('gbk')
df1 = get_title_content(date, page, link, html)
return df1
def thread_master():
"""把excel读取进来,然后一行一行放入队列中,这里起到生产作用"""
global end
# 此处的df是最后面的储存着每篇文章的excel表格。
length = len(df)
for i in range(length):
date, page, link = df.iloc[i,:]
page = int(page)
put_dom(date, page, link)
end = True
def put_dom(date, page, link):
"""具体的生产函数"""
df1 = parse(date, page, link)
[dom_queue.put(df1)]
def df_to_sql(df, name, idntt, root, host, db, pw, method):
"""将df存到mysql中,注意df的index需要有名字,叫做idntt,同时VARCHAR不可少,将text型的id转为VARCHAR型,host是用来连接数据库的ip,本地使用“localhost”,ip使用“IPV4”地址。method控制“replace”还是“append”。"""
basic_url = 'mysql+mysqldb://{root}:{pw}@{host}:3306/{db}?charset=utf8'.format(root=root, pw=pw, host=host, db=db)
engine = create_engine(basic_url)
conn = engine.connect()
df.to_sql(name, conn, if_exists='append',
dtype={idntt:VARCHAR(df.index.get_level_values(idntt).str.len().max())})
conn.close()
pass
def parse_dom():
while True:
if dom_queue.qsize() == 0 and end == True:
"""如果队列被全部存进去了MySQL(消耗结束)+master已经把原始链接生产结束(生产结束)"""
print("the end.")
break
elif dom_queue.qsize() == 0 and end == False:
time.sleep(10)
continue
try:
df1 = dom_queue.get()
df_to_sql(df1, name, idntt, root, host, db, pw, method)
except Exception as e:
dom_queue.put(df1)
def listen_thread():
"""监听程序"""
while True:
l = dom_queue.qsize()
print('current qsize len ',l)
time.sleep(10)
if l == 0 and end == True:
break
def schedule():
"""多线程"""
threading.Thread(target=listen_thread).start()
threading.Thread(target=thread_master).start()
for i in range(10):
threading.Thread(target=parse_dom).start()
dom_queue = Queue()
max_queue_size = 50000
end = False
name, idntt, root, host, db, pw, method = "newspaper", "link", "root", 你的ipv4, "人民日报", 你的密码, "append"
df = pd.read_csv(r'C:\Users\dell\Desktop\Tam\分年链接\df_1946.csv', index_col = [0], engine='python').iloc[:5000,:]
schedule()
这里的df格式如下,一共三列(列名分别是“date”是该日期,“page”是该日期的版面,“links”是该日期该版面的该文章的链接)。这里因为需要校园网才能够访问,因此大家可以把链接换成其他的链接。。当然爬虫规则需要改变。
图9:存放所有文章链接的原始excel
好啦,本文重点讲述了如何修改自己电脑中的MySQL的访问权限,同时简单带过了多线程爬取程序。希望对大家有一点作用。