关于初学python的一点问题总结(一)
目录
总结
这几天看了一下《python网络数据采集》,跟着书上差不多看了前面三章然后完成了一点书上的代码,这本书都是基于3.0以上的版本在写的,中间插入scrapy框架又需要用2.7版本。
页面抓取
首先是对整个html页面的抓取:
from urllib.request import urlopen
html=urlopen("http://baike.baidu.com")
print(html.read())
这个样子基本就可以拿下网页的html并输出到控制台上。
开始使用BeautifulSoup
-
通过python3中自带的pip程序(程序在\Python\Scripts),在cmd中运行,如图所示:
-
添加之后进行引用,然后就可以对页面DOM树直接进行操作,代码如下:
from bs4 import BeautifulSoup
from urllib.request import urlopen
html=urlopen("http://baike.baidu.com")
bsObj=BeautifulSoup(html.read(), "html.parser")
print(bsObj.title)
根据标签属性抽取数据
在BeautifulSoup的对象当中,通过find()和findAll()方法查询,产生Tag对象。然后使用Tag.get_text()就可以输出标签内容。具体的方法如下:
bsObj.findAll("div",{"class":"content"})
bsObj.findAll(class_="content")
对于兄弟,父母或者子标签,分别有对应的方法使用:.next_siblings() .parent 以及 .children
正则表达式
在某些标签的筛选中,可以使用正则表达式对特定的字符串进行筛选。这里有一个测试正则表达式的网站:RegexPal
关于正则表达式,具体的内容不再阐述,很多博客都有讲解。
开始过滤单个页面获取信息
首先通过遍历百度百科某个页面,结合正则表达式,并获取其中指向内部的<a>
标签
from bs4 import BeautifulSoup
from urllib.request import urlopen
import re
html=urlopen("http://baike.baidu.com/item/%E8%B5%B5%E6%B0%8F%E5%AD%A4%E5%84%BF/13828701")
bsObj=BeautifulSoup(html.read(), "html.parser")
btnList=bsObj.find("div",{"class":"body-wrapper"}).findAll("a",href=re.compile("^(/item/|/view/)"))
for btn in btnList:
if 'href' in btn.attrs:
print(btn.get_text())
print(btn.attrs['href'])
输出结果如下:
:
开始抓取内部链接数据
接下来就是开始对整个百度百科进行抓取,并将抓取内容输出到txt文件里面。代码如下:
# -*- coding: utf-8 -*-
import sys
from urllib.request import urlopen
from bs4 import BeautifulSoup
import datetime
import random
import re
# sys.setdefaultencoding('utf-8')
def getLinks(aUrl):
global pages
html=urlopen("http://baike.baidu.com"+aUrl)
bsObj=BeautifulSoup(html.read(),"html.parser")
links=bsObj.find("div",{"class":"body-wrapper"}).findAll("a",href=re.compile("^(/item/|/view/)"))
urlcontent=bsObj.find("div",{"class":"para"}).get_text()+"\n"
print("content:"+urlcontent)
f=open("baike.txt","a+",encoding='utf-8')
f.write(urlcontent)
for link in links:#开始抽取<a>标签的属性
if 'href' in link.attrs:
if link.attrs['href'] not in pages:
list=link.get_text()+" "+link.attrs['href']+"\n"
print(list)
f.write(list)
pages.add(link)
if link.attrs['href']=="/view/10812319.htm":#如果跳转到死链接就将链接初始化
link.attrs['href']="/item/%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98"
f.close()
return links
random.seed(datetime.datetime.now())
pages=set()
links=getLinks("/item/%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98")
while len(links)>0:
newArt=links[random.randint(0,len(links)-1)]
newArthref=newArt.attrs['href']
newArttitle=newArt.get_text()
result='----->'+newArttitle+' '+newArthref+"\n"
print("==============")
print(result)
f=open("baike.txt","a+",encoding='utf-8')
f.write(result)
f.close()
print("==============")
links=getLinks(newArthref)
整个代码将会开始进行一个死循环,然后开始持续抓取数据,然后将抓取的内部链接写进文本中。
最后说点
代码中间会产生重复的数据,将会在下次更新博客的时候解决。
写入文件时候的编码问题,在写入txt的时候,默认的txt文件编码为ANSI,需要先把txt的编码改变为utf-8,才能写入,否则会出现乱码。
内存溢出问题,在持续循环的时候,由于访问页面的增加,其中的request和response对象会直接存放在内存当中,这样会造成内存溢出,解决方案留在下次更新。