利⽤Python爬⾍爬取京东商品的简要信息
⼀、前⾔
  本⽂适合有⼀定Python基础的同学学习Python爬⾍,⽆基础请点击:
  申明:实例的主体框架来⾃于
  语⾔:Python2
  IDE:VScode
⼆、何为爬⾍
  传统爬⾍从⼀个或若⼲初始⽹页的URL开始,获得初始⽹页上的URL,然后下载队列中的URL地址对应的⽹页。解析后抓取⽹页内容,不断从当前页⾯上抽取新的URL放⼊队列,直到满⾜系统的⼀定停⽌条件。同时,它还会根据⼀定的搜索策略获取我们所需的信息并保存下来。最后为了展⽰我们爬到的数据,往往还会⽤HTML的表格或记事本保存我们所需要的数据。
  简单来说,爬⾍就是⼀门⽤来从互联⽹上⾃动获取我们所需数据的技术。
python正则表达式爬虫
三、JD商品详情页的⽹页分析
  我们需要分析的内容主要有:
  3.1详情页上指向的其他URL
    通过⿏标右键,查看元素,我们可以发现商品页⾯上的以上链接均为以下格式: //item.jd/数字.html
    分析到此,我们就知道抓取⽹页内容时,从当前页⾯上抽取新的URL的⽅法了。
  3.2商品名称、价格
  同理,我们在商品名称和价格处点击⿏标右键查看元素
四、简单爬⾍框架
  1.爬⾍总调度程序
    即我们的main⽂件,以⼊⼝URL为参数爬取所有相关页⾯
    维护待爬取和已爬取的URL列表
  3.HTML下载器
    主要功能是下载指定的url,这⾥⽤到了urllib2
  4.HTML解析器
    主要功能是获取⽹页上所需的URL和内容,⽤到BeautifulSoup     正则表达式的基础知识可以参见
    另外安利⼀个⽹站,在写正则表达式的时候可以先测试,很实⽤   
  5.输出程序
    将爬取到的数据写⼊HTML⽂件中,利⽤HTML的table展⽰
五、源码
  1.爬⾍总调度程序
import url_manager, html_downloader, html_parser, html_outputer
class SpiderMain(object):
def__init__(self):
self.urls = url_manager.UrlManager()
self.downloader = html_downloader.Html_DownloaDer()
self.parser = html_parser.HtmlParser()
self.outputer = html_outputer.HtmlOutputer()
#爬⾍调度程序
def craw(self, root_url):
count = 1
#⼊⼝URL添加进URL管理器
self.urls.add_new_url(root_url)
#启动循环,获取待扒取的URL,然后交给下载器下载页⾯,调⽤解析器解析页⾯while self.urls.has_new_url():
try:
new_url = _new_url()
print'craw',count, ':' ,new_url
html_cont = self.downloader.download(new_url)
#得到新的URL列表和内容
new_urls, new_data = self.parser.parse(new_url,html_cont)
#新的URL存到URL管理器,同时进⾏数据的收集
self.urls.add_new_urls(new_urls)
llect_data(new_data)
if count == 10:
break
count = count +1
except:
print'craw dailed'
#调⽤output_html展⽰爬取到的数据
self.outputer.output_html()
if__name__ == "__main__":
#⼊⼝URL
root_url = "item.jd/4224129.html"
obj_spider = SpiderMain()
#启动爬⾍
aw(root_url)
  2.URL管理器
class UrlManager(object):
def__init__(self):
#未爬取URL列表,已爬取URL列表
self.old_urls = set()
#判断管理器中是否有新的待扒取的URL
def has_new_url(self):
return w_urls) != 0
#获取⼀个新的待扒取的URL
def get_new_url(self):
#pop⽅法:获取列表中的⼀个URL并移除它
new_url = w_urls.pop()
self.old_urls.add(new_url)
return new_url
#向管理器添加⼀个新的URL
def add_new_url(self, url):
if url is None:
return
#发现新的未添加的URL,则加⼊待扒取URL列表
if url not w_urls and url not in self.old_urls:
#向管理器添加批量个新的URL
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url)
  3.HTML下载器
import urllib2
class Html_DownloaDer():
def download(self, url):
return None
#调⽤urllib2库的urlopen⽅法获取类⽂件对象(fd) response
""" response = urllib2.urlopen(url)"""
#调⽤urllib2库的Request⽅法创建request对象
request = urllib2.Request(url)
#添加数据
request.add_data('a')
#添加htp和header(伪装成浏览器)
request.add_header('User-Agent','Mozilla/5.0')
#发送请求获取结果
response = urllib2.urlopen(request)
#获取状态码,200表⽰成功
de() != 200:
return None
ad()
  4.HTML解析器
from bs4 import BeautifulSoup
import re
import urlparse
class HtmlParser(object):
def _get_new_urls(self, page_url, soup):
new_urls = set()
#获取所有的链接
#格式如:<a target="_blank" title="华为(HUAWEI)..." href="//item.jd/12943624333.html">
links = soup.find_all('a',href = repile(r"//item.jd/\d+\.htm"))
#遍历转化为完整的URL
for link in links:
new_url = link['href']
new_full_url = urlparse.urljoin(page_url,new_url)
#将结果存到⼀个新的列表⾥
new_urls.add(new_full_url)
return new_urls
def _new_data(self, page_url, soup):
res_data = {}
#URL
res_data['url'] = page_url
#匹配标题
#<div class="sku-name">华为(HUAWEI) MateBook X 13英⼨超轻薄微边框笔记本(i5-7200U 4G 256G 拓展坞 2K屏指纹背光 office)灰</div>        title_node = soup.find('div',class_ = "sku-name")
res_data['title'] = _text()
#匹配价格
#<div class="dd">
#<span class="p-price"><span>¥</span><span class="price J-p-7430495">4788.00</span></span>
"""下载的⽹页源码⽆价格信息<span class="price J-p-7430495"></span></span>"""
price_node = soup.find('span',class_ = repile(r"price\sJ\-p\-\d+"))
res_data['price'] =_text()
return res_data
def parse(self, page_url, html_cont):
if page_url is None or html_cont is None:
return
soup = BeautifulSoup(html_cont,'html.parser')
new_urls = self._get_new_urls(page_url,soup)
_new_data = self._new_data(page_url,soup)
return new_urls, _new_data
  5.输出程序
class HtmlOutputer(object):
def__init__(self):
self.datas = []
def collect_data(self,data):
if data is None:
return
self.datas.append(data)
def output_html(self):
fout = open('output.html','w')
fout.write("<html>")
fout.write("<head>")
fout.write('<meta charset="UTF-8">')
fout.write("<body>")
fout.write("<table>")
#python默认编码是ascii,中⽂可能会乱码,故加上encode('utf-8')
for data in self.datas:
fout.write("<tr>")
fout.write("<td>%s</td>" % data['url'])
fout.write("<td>%s</td>" % data['title'].encode('utf-8'))
fout.write("<td>%s</td>" % data['price'].encode('utf-8'))
fout.write("</tr>")
fout.write("</table>")
fout.write("</body>")
fout.write("</head>")
fout.write("</html>")
六、待解决问题
  关于我爬取不到价格的问题...
  调试中发现我已爬取到了对应的内容,唯独少了价格...⼀度扎⼼啊...
  在上看到以下论述
  但是...我查看源码的时候真的是有价格的啊...求⼤神解惑ps:第⼀次写博客,思路不是很清晰,欢迎学习交流指正。