5行代码就能入门爬虫?

百家 作者:AI100 2019-02-17 14:16:15


作者?|?苏克1900

来源 |?第2大脑(ID:Mocun6

责编?|?swallow


不少读者是刚刚入门Python或者想学习Python的,今天就来谈谈如何用快速入门爬虫。


先说结论:入门爬虫很容易,几行代码就可以,可以说是学习Python最简单的途径。


以我纯小白、零基础的背景来说,入门爬虫其实很容易,容易在代码编写很简单,简单的爬虫通常几行就能搞定,而不容易在确定爬虫的目标,也就是说为什么要去写爬虫,有没有必要用到爬虫,是不是手动操作几乎无法完成,互联网上有数以百万千万计的网站,到底以哪一个网站作为入门首选,这些问题才是难点。所以在动手写爬虫前,最好花一些时间想一想这清楚这些问题。


「Talk is cheap. Show me the code」,下面我就以曾写过的一个爬虫为例,说一说我是如何快速入门Python爬虫的。


▌确立目标


第一步,确立目标。


为什么想起写这个爬虫呢,是因为这是曾经在工作中想要解决的问题,当时不会爬虫,只能用Excel花了数个小时才勉强地把数据爬了下来, 所以在接触到爬虫后,第一个想法就是去实现曾未实现的目标。以这样的方式入门爬虫,好处显而易见,就是有了很明确的动力。


很多人学爬虫都是去爬网上教程中的那些网站,网站一样就算了,爬取的方法也一模一样,等于抄一遍,不是说这样无益,但是会容易导致动力不足,因为你没有带着目标去爬,只是为了学爬虫而爬,爬虫虽然是门技术活,但是如果能建立在兴趣爱好或者工作任务的前提下,学习的动力就会强很多。


在确定好爬虫目标后,接着我就在脑中预想了想要得到什么样的结果、如何展示出来、以什么形式展现这些问题。所以,我在爬取网站之前,就预先构想出了想要的一个结果,大致是下面这张图的样子。



目标是利用爬下来的数据,尝试从不同维度年份、省份、城市去分析全国的股市信息,然后通过可视化图表呈现出来。


抛开数据,可能你会觉得这张图在排版布局、色彩搭配、字体文字等方面还挺好看的。这些呢,就跟爬虫没什么关系了,而跟审美有关,提升审美的一种方式是可以通过做PPT来实现,所以你看,咱们说着说着就从爬虫跳到了 PPT,不得不说我此前发的文章铺垫地很好啊,哈哈。其实,在职场中,你拥有的技能越多越好。


▌直接开始


确定了目标后,第二步就可以开始写爬虫了,如果你像我一样,之前没有任何编程基础,那我下面说的思路,可能会有用。


刚开始动手写爬虫,我只关注最核心的部分,也就是先成功抓到数据,其他的诸如:下载速度、存储方式、代码条理性等先不管,这样的代码简短易懂、容易上手,能够增强信心。


所以,我在写第一遍的时候,只用了5行代码,就成功抓取了全部所需的信息,当时的感觉就是很爽,觉得爬虫不过如此啊,自信心爆棚。


1import?pandas?as?pd
2import?csv
3for?i?in?range(1,178):??#?爬取全部页
4????tb?=?pd.read_html('http://s.askci.com/stock/a/?reportTime=2017-12-31&pageNum=%s'?%?(str(i)))[3]?
5????tb.to_csv(r'1.csv',?mode='a',?encoding='utf_8_sig',?hea


3000+ 上市公司的信息,安安静静地躺在 Excel 中:



▌不断完善


有了上面的信心后,我开始继续完善代码,因为5行代码太单薄,功能也太简单,大致从以下几个方面进行了完善:


  • 增加异常处理


由于爬取上百页的网页,中途很可能由于各种问题导致爬取失败,所以增加了 try except 、if 等语句,来处理可能出现的异常,让代码更健壮。


  • 增加代码灵活性


初版代码由于固定了URL参数,所以只能爬取固定的内容,但是人的想法是多变的,一会儿想爬这个一会儿可能又需要那个,所以可以通过修改 URL 请求参数,来增加代码灵活性,从而爬取更灵活的数据。


  • 修改存储方式


初版代码我选择了存储到Excel这种最为熟悉简单的方式,人是一种惰性动物,很难离开自己的舒适区。但是为了学习新知识,所以我选择将数据存储到 MySQL 中,以便练习 MySQL 的使用。


  • 加快爬取速度


初版代码使用了最简单的单进程爬取方式,爬取速度比较慢,考虑到网页数量比较大,所以修改为了多进程的爬取方式。


经过以上这几点的完善,代码量从原先的5行增加到了下面的几十行:


?1import?requests
?2import?pandas?as?pd
?3from?bs4?import?BeautifulSoup
?4from?lxml?import?etree
?5import?time
?6import?pymysql
?7from?sqlalchemy?import?create_engine
?8from?urllib.parse?import?urlencode??#?编码?URL?字符串
?9
10start_time?=?time.time()??#计算程序运行时间
11def?get_one_page(i):
12????try:
13????????headers?=?{
14????????????'User-Agent':?'Mozilla/5.0?(Windows?NT?6.1;?WOW64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/66.0.3359.181?Safari/537.36'
15????????}
16????????paras?=?{
17????????'reportTime':?'2017-12-31',
18????????#可以改报告日期,比如2018-6-30获得的就是该季度的信息
19????????'pageNum':?i???#页码
20????????}
21????????url?=?'http://s.askci.com/stock/a/?'?+?urlencode(paras)
22????????response?=?requests.get(url,headers?=?headers)
23????????if?response.status_code?==?200:
24????????????return?response.text
25????????return?None
26????except?RequestException:
27????????print('爬取失败')
28
29def?parse_one_page(html):
30????soup?=?BeautifulSoup(html,'lxml')
31????content?=?soup.select('#myTable04')[0]?#[0]将返回的list改为bs4类型
32????tbl?=?pd.read_html(content.prettify(),header?=?0)[0]
33????#?prettify()优化代码,[0]从pd.read_html返回的list中提取出DataFrame
34????tbl.rename(columns?=?{'序号':'serial_number',?'股票代码':'stock_code',?'股票简称':'stock_abbre',?'公司名称':'company_name',?'省份':'province',?'城市':'city',?'主营业务收入(201712)':'main_bussiness_income',?'净利润(201712)':'net_profit',?'员工人数':'employees',?'上市日期':'listing_date',?'招股书':'zhaogushu',?'公司财报':'financial_report',?'行业分类':'industry_classification',?'产品类型':'industry_type',?'主营业务':'main_business'},inplace?=?True)
35????return?tbl
36
37def?generate_mysql():
38????conn?=?pymysql.connect(
39????????host='localhost',
40????????user='root',
41????????password='******',
42????????port=3306,
43????????charset?=?'utf8',??
44????????db?=?'wade')
45????cursor?=?conn.cursor()
46
47????sql?=?'CREATE?TABLE?IF?NOT?EXISTS?listed_company?(serial_number?INT(20)?NOT?NULL,stock_code?INT(20)?,stock_abbre?VARCHAR(20)?,company_name?VARCHAR(20)?,province?VARCHAR(20)?,city?VARCHAR(20)?,main_bussiness_income?VARCHAR(20)?,net_profit?VARCHAR(20)?,employees?INT(20)?,listing_date?DATETIME(0)?,zhaogushu?VARCHAR(20)?,financial_report?VARCHAR(20)?,?industry_classification?VARCHAR(20)?,industry_type?VARCHAR(100)?,main_business?VARCHAR(200)?,PRIMARY?KEY?(serial_number))'
48????cursor.execute(sql)
49????conn.close()
50
51def?write_to_sql(tbl,?db?=?'wade'):
52????engine?=?create_engine('mysql+pymysql://root:******@localhost:3306/{0}?charset=utf8'.format(db))
53????try:
54????????tbl.to_sql('listed_company2',con?=?engine,if_exists='append',index=False)
55????????#?append表示在原有表基础上增加,但该表要有表头
56????except?Exception?as?e:
57????????print(e)
58
59def?main(page):
60????generate_mysql()
61????for?i?in?range(1,page):??
62????????html?=?get_one_page(i)
63????????tbl?=?parse_one_page(html)
64????????write_to_sql(tbl)
65
66#?#?单进程
67if?__name__?==?'__main__':????
68????main(178)
69????endtime?=?time.time()-start_time
70????print('程序运行了%.2f秒'?%endtime)
71
72#?多进程
73from?multiprocessing?import?Pool
74if?__name__?==?'__main__':
75?????pool?=?Pool(4)
76?????pool.map(main,?[i?for?i?in?range(1,178)])??#共有178页
77????endtime?=?time.time()-start_time
78????print('程序运行了%.2f秒'?%(time.time()-start_time))


虽然代码行数增加了不少,但是这个过程却觉得很自然,因为每次修改都是针对一个小点,一点点去学,搞懂后添加进来,而如果让我上来就直接写出这几十行的代码,我很可能就放弃了。


所以,你可以看到,入门爬虫是有套路的,最重要的是给自己信心。


(本文仅代表作者观点,转载请联系原作者)

精彩推荐

推荐阅读:

? ? ? ? ? ? ? ? ? ? ? ? ?

点击“阅读原文”,打开CSDN?APP?阅读更贴心。

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接